SQL Server ma systemową procedurę składowaną o nazwie sp_estimate_data_compression_savings
, który pozwala sprawdzić rozmiar obiektu i jego szacowany rozmiar przy różnych poziomach kompresji.
Jeśli obiekt jest już skompresowany, możesz użyć tej procedury, aby oszacować jego rozmiar po ponownej kompresji.
Obiekty można skompresować za pomocą kompresji wierszy, stron, magazynu kolumn lub archiwum magazynu kolumn.
Kompresja może być oceniana dla całych tabel lub ich części. Obejmuje to sterty, indeksy klastrowe, indeksy nieklastrowane, indeksy magazynu kolumn, widoki indeksowane oraz partycje tabel i indeksów.
Przykład
Oto przykład do zademonstrowania.
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemHoldings',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'ROW';
Wynik:
+-------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+ | object_name | schema_name | index_id | partition_number | size_with_current_compression_setting(KB) | size_with_requested_compression_setting(KB) | sample_size_with_current_compression_setting(KB) | sample_size_with_requested_compression_setting(KB) | |-------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------| | StockItemHoldings | Warehouse | 1 | 1 | 32 | 8 | 40 | 16 | +-------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+
Aby oszczędzić Ci konieczności zbyt częstego przewijania w bok, tutaj ponownie używamy pionowego wyjścia:
-[ RECORD 1 ]------------------------- object_name | StockItemHoldings schema_name | Warehouse index_id | 1 partition_number | 1 size_with_current_compression_setting(KB) | 32 size_with_requested_compression_setting(KB) | 8 sample_size_with_current_compression_setting(KB) | 40 sample_size_with_requested_compression_setting(KB) | 16
Rozmiary kompresji podane są w kilobajtach (KB).
W tym przypadku wydaje się, że stosowanie kompresji wierszy w tej tabeli przynosi znaczną korzyść. Przechodzi od 32 KB do 8 KB. Zakłada się, że jest to dokładne oszacowanie.
Kiedy uruchomiłem poprzedni kod, podałem wszystkie nazwy argumentów. Możesz również pominąć te nazwy i po prostu podać wartości.
Tak:
EXEC sp_estimate_data_compression_savings
'Warehouse',
'StockItemHoldings',
NULL,
NULL,
'ROW';
Tak czy inaczej, wynik jest taki sam.
Tutaj jest znowu, ale tym razem określam PAGE
zamiast ROW
jako typ kompresji.
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemHoldings',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'PAGE';
Wynik (przy użyciu wyjścia pionowego):
-[ RECORD 1 ]------------------------- object_name | StockItemHoldings schema_name | Warehouse index_id | 1 partition_number | 1 size_with_current_compression_setting(KB) | 32 size_with_requested_compression_setting(KB) | 8 sample_size_with_current_compression_setting(KB) | 40 sample_size_with_requested_compression_setting(KB) | 16
W tym przypadku liczby wyglądają tak samo, ale w zależności od danych możesz uzyskać bardzo różne liczby.
Typy kompresji
@data_compression
argument przyjmuje następujące wartości:
BRAK
ROW
STRONA
SKLEP KOLUMN
COLUMNSTORE_ARCHIVE
Oto opcje kompresji dostępne podczas tworzenia/zmiany tabeli lub indeksu.
SKLEP KOLUMN
i COLUMNSTORE_ARCHIVE
opcje są dostępne tylko w przypadku indeksów magazynu kolumn (w tym zarówno nieklastrowanych, jak i klastrowanych indeksów magazynu kolumn).
@index_id
Argument
Czasami wyniki mogą zwracać wiele wierszy dla danego obiektu, każdy z innym index_id .
Jeśli wolisz, możesz zawęzić go do określonego indeksu. Aby to zrobić, podaj index_id do @index_id
argument.
Na przykład, kiedy uruchamiam poniższy kod, zwracanych jest osiem wierszy, każdy z innym index_id wartości.
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemTransactions',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'ROW';
Wynik:
+-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+ | object_name | schema_name | index_id | partition_number | size_with_current_compression_setting(KB) | size_with_requested_compression_setting(KB) | sample_size_with_current_compression_setting(KB) | sample_size_with_requested_compression_setting(KB) | |-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------| | StockItemTransactions | Warehouse | 2 | 1 | 5568 | 4120 | 4280 | 3168 | | StockItemTransactions | Warehouse | 3 | 1 | 5184 | 3720 | 4264 | 3064 | | StockItemTransactions | Warehouse | 4 | 1 | 5568 | 4224 | 4288 | 3256 | | StockItemTransactions | Warehouse | 5 | 1 | 5528 | 4416 | 4280 | 3424 | | StockItemTransactions | Warehouse | 6 | 1 | 5192 | 3456 | 4264 | 2840 | | StockItemTransactions | Warehouse | 7 | 1 | 5192 | 3464 | 4264 | 2848 | | StockItemTransactions | Warehouse | 9 | 1 | 5416 | 4456 | 4264 | 3512 | | StockItemTransactions | Warehouse | 1 | 1 | 2720 | 9096 | 2720 | 9096 | +-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+
Gdybyśmy chcieli zawęzić go do jednego wiersza, moglibyśmy użyć jego index_id .
Tak:
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemTransactions',
@index_id =1,
@partition_number = NULL,
@data_compression = 'ROW';
Wynik:
+-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+ | object_name | schema_name | index_id | partition_number | size_with_current_compression_setting(KB) | size_with_requested_compression_setting(KB) | sample_size_with_current_compression_setting(KB) | sample_size_with_requested_compression_setting(KB) | |-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------| | StockItemTransactions | Warehouse | 1 | 1 | 2720 | 9096 | 2720 | 9096 | +-----------------------+---------------+------------+--------------------+---------------------------------------------+-----------------------------------------------+----------------------------------------------------+------------------------------------------------------+
Możesz także użyć @numer_partycji zrobić to samo z partycjami.
Ilość kompresji może się znacznie różnić
Stopień kompresji, jaki uzyskasz, będzie zależeć od danych i rodzaju kompresji.
ROW
kompresja, na przykład, usuwa niepotrzebne bajty z wartości kolumn, przechowując je w formacie o zmiennej długości. PAGE
z drugiej strony kompresja przechowuje powtarzające się wartości tylko raz na stronę i ustawia wskaźnik z odpowiednich kolumn na stronie.
Czasami może się okazać, że kompresja obiektu nie zawsze zmniejsza jego rozmiar, a w niektórych przypadkach może nawet zwiększyć jego rozmiar.
Może się tak zdarzyć, jeśli Twoje kolumny używają typu danych, który nie korzysta z kompresji.
Ponadto kompresja wierszy zmniejsza obciążenie metadanych, ale w niektórych przypadkach obciążenie może być większe niż w przypadku starego formatu przechowywania.
Jeśli Twoje dane nie uzyskują żadnych korzyści z kompresji ze względu na ich typ danych, prawdopodobne jest, że obciążenie spowoduje wzrost wymagań dotyczących pamięci, a nie ich spadek.
Jednak różnice w rozmiarze kompresji będą również zależeć od rzeczywistych danych. Na przykład, jeśli masz znak(10) kolumna, kompresja usunie wszystkie końcowe znaki dopełnienia. Jeśli masz wiele wierszy ze znakami dopełnienia końcowego, powinieneś uzyskać lepszy wynik niż w przypadku braku (lub kilku) wierszy ze znakami dopełnienia końcowego.
Jak szacuje kompresję?
Po wykonaniu sp_estimate_data_compression_savings
, pobiera próbkę danych, a następnie ładuje je do równoważnej tabeli i indeksu utworzonego w tempdb . Utworzenie tabeli lub indeksu w tempdb jest następnie kompresowany do żądanego ustawienia i obliczane są szacunkowe oszczędności kompresji.
Jak to jest dokładne?
Możesz uzyskać mieszane wyniki podczas korzystania z sp_estimate_data_compression_savings
.
Przeprowadźmy mały test.
SELECT * INTO Warehouse.StockItemTransactions2
FROM Warehouse.StockItemTransactions;
EXEC sp_spaceused 'Warehouse.StockItemTransactions2';
Wynik (przy użyciu wyjścia pionowego):
name | StockItemTransactions2 rows | 236667 reserved | 15944 KB data | 15800 KB index_size | 8 KB unused | 136 KB
sp_spaceused
procedura składowana pokazuje nam faktycznie wykorzystane miejsce na dysku. W tym przypadku dane zajmują 15 800 KB miejsca na dysku.
Teraz wykonam sp_estimate_data_compression_savings
aby zobaczyć, jaką oszczędność miejsca uzyskam, jeśli zastosuję kompresję do tej tabeli.
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemTransactions2',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'ROW';
Wynik (przy użyciu wyjścia pionowego):
object_name | StockItemTransactions2 schema_name | Warehouse index_id | 0 partition_number | 1 size_with_current_compression_setting(KB) | 15808 size_with_requested_compression_setting(KB) | 9096 sample_size_with_current_compression_setting(KB) | 15800 sample_size_with_requested_compression_setting(KB) | 9096
Zgodnie z tymi wynikami zastosowanie kompresji wierszy do tej tabeli zmniejszy jej rozmiar z 15 808 KB do szacowanego rozmiaru zaledwie 9096 KB. Nie tak źle.
Zastosujmy teraz kompresję wierszy do tej tabeli, a następnie uruchommy sp_spaceused
ponownie.
ALTER TABLE Warehouse.StockItemTransactions2
REBUILD WITH (DATA_COMPRESSION = ROW);
EXEC sp_spaceused 'Warehouse.StockItemTransactions2';
Wynik (przy użyciu wyjścia pionowego):
name | StockItemTransactions2 rows | 236667 reserved | 9160 KB data | 9088 KB index_size | 8 KB
Tak więc rzeczywisty wynik jest bardzo zbliżony do wyniku szacunkowego.
W takim przypadku sp_estimate_data_compression_savings
dostarczyło dość dokładne oszacowanie wyniku końcowego.
Uruchommy sp_estimate_data_compression_savings
jeszcze raz, ale przy użyciu typu kompresji BRAK
.
EXEC sp_estimate_data_compression_savings
@schema_name = 'Warehouse',
@object_name = 'StockItemTransactions2',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'NONE';
Wynik:
object_name | StockItemTransactions2 schema_name | Warehouse index_id | 0 partition_number | 1 size_with_current_compression_setting(KB) | 9096 size_with_requested_compression_setting(KB) | 15808 sample_size_with_current_compression_setting(KB) | 9096 sample_size_with_requested_compression_setting(KB) | 15808
To mówi nam, co by się stało, gdybyśmy wrócili do braku kompresji.
W tym przypadku pokazuje nam dokładnie tę samą liczbę (15 808 KB), którą pokazał nam przed zastosowaniem kompresji, która, jak pamiętasz, była dość zbliżona do rzeczywistego rozmiaru (15 800 KB) zwróconego przez sp_spaceused procedura.
Więc uruchommy go jeszcze raz i przekonajmy się.
ALTER TABLE Warehouse.StockItemTransactions2
REBUILD WITH (DATA_COMPRESSION = NONE);
EXEC sp_spaceused 'Warehouse.StockItemTransactions2';
Wynik (przy użyciu wyjścia pionowego):
name | StockItemTransactions2 rows | 236667 reserved | 15880 KB data | 15800 KB index_size | 8 KB unused | 72 KB
Więc znowu, sp_estimate_data_compression_savings
był prawie na miejscu.
To jednak tylko jeden prosty test. Inne testy mogą zwrócić szacunki, które są odległe. Czytałem historie o sp_estimate_data_compression_savings
zwracam szalenie niedokładne wyniki, ale sam jeszcze tego nie doświadczyłem.
Dlatego wydaje się, że sp_estimate_data_compression_savings
może zapewnić dokładne oszacowanie w tych samych przypadkach, a nie w innych.
Musisz zdecydować, na ile polegasz na tej procedurze składowanej. W każdym razie prawdopodobnie powinieneś uruchomić test w swoim środowisku programistycznym lub testowym przed zastosowaniem kompresji w środowisku produkcyjnym.