Alternatywny sposób kompresji NVARCHAR (MAX)?

14

Próbuję skompresować niektóre tabele zawierające NVARCHAR(MAX)pola. Niestety, rowa pagekompresja nie mają wpływu pragnienie (tylko ~ 100/200 MB do 20 GB zapisanej tabeli). Ponadto nie jestem w stanie zastosować kompresji archiwizacji magazynu kolumn i magazynu kolumn, ponieważ nie obsługują one kompresji NVARCHAR(MAX)pól.

Czy ktoś może powiedzieć, czy mam tutaj jakieś alternatywy?

Ja również odgadnąć rowi pagekompresja nie mają wpływu, ponieważ zawartość NVARCHAR(MAX)kolumn jest wyjątkowy.

gotqn
źródło
2
Czy wartości kolumn są zdecydowanie szersze niż 8000 znaków? np. SELECT MAX (CAST (LEN (widecolumn) AS BIGINT)) FROM dbo.largeTable W przeciwnym razie możesz przekonwertować je na zwykły varchar i zastosować klastrowany magazyn kolumn.
wBob
@wBob Nawet jeśli największa wartość wynosiła tylko 2000 znaków, czy nie przekształciłaby się w VARCHARpotencjalną utratę danych, gdyby używane były znaki z więcej niż 1 strony kodowej? Sądzę, że zaleceniem jest konwersja, NVARCHAR(4000)jeśli maksymalna długość nie jest większa niż 4000, ponieważ wtedy wszystkie wartości kwalifikują się do pełnej kompresji Unicode. Mimo to prawdopodobnie bezpiecznie jest założyć na podstawie informacji zawartych w pytaniu, że wartości mają znacznie ponad 4000 znaków, dlatego obecnie nie kompresują się.
Solomon Rutzky 18.04.16

Odpowiedzi:

16

Kompresja stron i wierszy nie kompresuje obiektów BLOB .

Ze względu na swój rozmiar typy danych o dużej wartości są czasami przechowywane osobno od normalnych danych wierszy na stronach specjalnego przeznaczenia. Kompresja danych nie jest dostępna dla danych przechowywanych osobno.

Jeśli chcesz kompresować obiekty BLOB, musisz je zapisać jako VARBINARY(MAX)i zastosować wybrany algorytm kompresji strumienia. Na przykład GZipStream. Istnieje wiele przykładów, jak to zrobić, wystarczy wyszukać GZipStream i SQLCLR.

Remus Rusanu
źródło
10

Istnieją (obecnie) potencjalnie dwa sposoby uzyskania niestandardowej kompresji:

  1. Począwszy od SQL Server 2016 są wbudowane funkcje COMPRESS i DECOMPRESS . Funkcje te używają algorytmu GZip.

  2. Użyj SQLCLR, aby zaimplementować dowolny wybrany algorytm (jak wspomniano w odpowiedzi na @Remus). Ta opcja jest dostępna w wersjach wcześniejszych niż SQL Server 2016, począwszy od SQL Server 2005.

    GZip jest łatwym wyborem, ponieważ jest dostępny w .NET i obsługiwanych bibliotekach .NET Framework (kod może znajdować się w SAFEasemblerze). Lub, jeśli chcesz GZip, ale nie chcesz zajmować się kodowaniem / wdrażaniem go, możesz użyć funkcji Util_GZip i Util_GUnzip, które są dostępne w bezpłatnej wersji biblioteki SQL # SQLCLR (której jestem autorem).

    Jeśli zdecydujesz się na użycie GZip, bez względu na to, czy kodujesz sam, czy używasz SQL #, pamiętaj, że algorytm użyty w .NET do kompresji GZip został zmieniony w Framework Framework 4.5 na lepsze (zobacz sekcję „Uwagi” na MSDN strona dla klasy GZipStream ). To znaczy:

    1. Jeśli używasz programu SQL Server 2005, 2008 lub 2008 R2 - wszystkie powiązane z CLR v 2.0, który obsługuje wersje Framework 2.0, 3.0 i 3.5 - zmiana dokonana w wersji 4.5 nie ma wpływu i niestety utkniesz Oryginalny, podstępny algorytm .NET.
    2. Jeśli używasz programu SQL Server 2012 lub nowszego (do tej pory 2014 i 2016) - wszystkie powiązane z CLR v 4.0, który obsługuje wersje Framework 4.0, 4.5.x, 4.6 - możesz użyć nowszego, lepszego algorytmu. Jedynym wymaganiem jest zaktualizowanie systemu .NET Framework na serwerze z programem SQL Server do wersji 4.5 lub nowszej.

    Jednak nie musisz używać GZip i możesz dowolnie implementować dowolny algorytm.

UWAGA: wszystkie wyżej wymienione metody są bardziej „obejściami” niż rzeczywistymi zamiennikami, mimo że są technicznie „alternatywnymi sposobami kompresji danych NVARCHAR (MAX)”. Różnica polega na tym, że dzięki wbudowanej kompresji danych - rowi page- oferowanej przez SQL Server, kompresja jest obsługiwana za kulisami, a dane są nadal użyteczne, czytelne i indeksowalne. Ale kompresja dowolnych danych VARBINARYoznacza, że ​​oszczędzasz miejsce, ale rezygnujesz z niektórych funkcji. To prawda, że ​​ciąg 20k i tak nie jest indeksowalny, ale nadal można go użyć wWHEREklauzula lub dowolne funkcje łańcuchowe. Aby zrobić cokolwiek z niestandardową skompresowaną wartością, musisz ją rozpakować w locie. Podczas kompresji plików binarnych (PDF, JPEG itp.) Nie stanowi to problemu, ale pytanie dotyczyło NVARCHARdanych.

Solomon Rutzky
źródło