Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Schätzen Sie die Einsparungen bei der Datenkomprimierung in SQL Server

SQL Server verfügt über eine gespeicherte Systemprozedur namens sp_estimate_data_compression_savings , mit dem Sie die Größe eines Objekts und seine geschätzte Größe mit verschiedenen Komprimierungsstufen überprüfen können.

Wenn das Objekt bereits komprimiert ist, können Sie dieses Verfahren verwenden, um seine Größe nach der erneuten Komprimierung abzuschätzen.

Objekte können mithilfe der Zeilen-, Seiten-, Columnstore- oder Columnstore-Archivkomprimierung komprimiert werden.

Die Komprimierung kann für ganze Tabellen oder Teile von Tabellen ausgewertet werden. Dazu gehören Heaps, Clustered-Indizes, Nonclustered-Indizes, Columnstore-Indizes, indizierte Ansichten sowie Tabellen- und Indexpartitionen.

Beispiel

Hier ist ein Beispiel zur Veranschaulichung.

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemHoldings', 
    @index_id = NULL, 
    @partition_number = NULL, 
    @data_compression = 'ROW'; 

Ergebnis:

+-------------------+----------+---------- -----------------------+--------------------- -------------------+------------------------------ ------------------+------------------------------- --------------------+----------------------------- -------------------------+| Objektname | Schemaname | index_id | Partitionsnummer | 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 | Lager | 1 | 1 | 32 | 8 | 40 | 16 |+--------------+----------+----------- -+--------------------+--------------------- ------------------+------------------------------- ----------------+--------------------------------- -------------------+------------------------------ ------------------------+

Damit Sie nicht zu viel seitwärts scrollen müssen, wird hier wieder die vertikale Ausgabe verwendet:

-[ RECORD 1 ]--------------------Objektname | StockItemHoldingsschema_name | Warehouseindex_id | 1Partitionsnummer | 1size_with_current_compression_setting(KB) | 32size_with_requested_compression_setting(KB) | 8sample_size_with_current_compression_setting(KB) | 40sample_size_with_requested_compression_setting(KB) | 16

Die Komprimierungsgrößen sind in Kilobyte (KB) angegeben.

In diesem Fall scheint es einen erheblichen Vorteil zu geben, die Zeilenkomprimierung für diese Tabelle zu verwenden. Es geht von 32 KB bis 8 KB. Dies setzt voraus, dass es sich um eine genaue Schätzung handelt.

Als ich den vorherigen Code ausgeführt habe, habe ich alle Argumentnamen angegeben. Sie können diese Namen auch weglassen und nur die Werte angeben.

So:

EXEC sp_estimate_data_compression_savings 
    'Warehouse', 
    'StockItemHoldings', 
    NULL, 
    NULL, 
    'ROW'; 

In beiden Fällen ist das Ergebnis dasselbe.

Hier ist es wieder, aber diesmal gebe ich PAGE an statt ROW als Komprimierungstyp.

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemHoldings', 
    @index_id = NULL, 
    @partition_number = NULL, 
    @data_compression = 'PAGE'; 

Ergebnis (bei vertikaler Ausgabe):

-[ RECORD 1 ]--------------------Objektname | StockItemHoldingsschema_name | Warehouseindex_id | 1Partitionsnummer | 1size_with_current_compression_setting(KB) | 32size_with_requested_compression_setting(KB) | 8sample_size_with_current_compression_setting(KB) | 40sample_size_with_requested_compression_setting(KB) | 16

In diesem Fall sehen die Zahlen gleich aus, aber abhängig von Ihren Daten könnten Sie sehr unterschiedliche Zahlen erhalten.

Komprimierungsarten

Die @data_compression Das Argument akzeptiert die folgenden Werte:

  • NONE
  • ROW
  • PAGE
  • COLUMNSTORE
  • COLUMNSTORE_ARCHIVE

Dies sind die Komprimierungsoptionen, die beim Erstellen/Ändern einer Tabelle oder eines Index verfügbar sind.

Der COLUMNSTORE und COLUMNSTORE_ARCHIVE Optionen sind nur für Columnstore-Indizes verfügbar (einschließlich nicht gruppierter Columnstore- und Clustered Columnstore-Indizes).

Der @index_id Argument

Manchmal geben Ihre Ergebnisse möglicherweise mehrere Zeilen für ein bestimmtes Objekt zurück, jede mit einer anderen index_id .

Sie können es auf einen bestimmten Index eingrenzen, wenn Sie dies bevorzugen. Geben Sie dazu die index_id an zu @index_id Argument.

Wenn ich beispielsweise den folgenden Code ausführe, werden acht Zeilen zurückgegeben, jede mit einer anderen index_id Werte.

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemTransactions', 
    @index_id = NULL, 
    @partition_number = NULL, 
    @data_compression = 'ROW'; 

Ergebnis:

+-----------------------+---------------+------ ------+--------------------+--------------------- -----------------------+--------------------- ---------------------+------------------------------------ ------------------------+-------------------- -----------------------------+| Objektname | Schemaname | index_id | Partitionsnummer | 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 | Lager | 2 | 1 | 5568 | 4120 | 4280 | 3168 || StockItemTransactions | Lager | 3 | 1 | 5184 | 3720 | 4264 | 3064 || StockItemTransactions | Lager | 4 | 1 | 5568 | 4224 | 4288 | 3256 || StockItemTransactions | Lager | 5 | 1 | 5528 | 4416 | 4280 | 3424 || StockItemTransactions | Lager | 6 | 1 | 5192 | 3456 | 4264 | 2840 || StockItemTransactions | Lager | 7 | 1 | 5192 | 3464 | 4264 | 2848 || StockItemTransactions | Lager | 9 | 1 | 5416 | 4456 | 4264 | 3512 || StockItemTransactions | Lager | 1 | 1 | 2720 ​​| 9096 | 2720 ​​| 9096 |+-----------------------+---------------+------- -----+--------------------+------------------------------- ----------------------+---------------------- --------------------+----------------------------- -----------------------+--------------------- ----------------------------+

Wenn wir es auf nur eine Zeile eingrenzen wollten, könnten wir seine index_id verwenden .

So:

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemTransactions', 
    @index_id =1, 
    @partition_number = NULL, 
    @data_compression = 'ROW'; 

Ergebnis:

+-----------------------+---------------+------ ------+--------------------+--------------------- -----------------------+--------------------- ---------------------+------------------------------------ ------------------------+-------------------- -----------------------------+| Objektname | Schemaname | index_id | Partitionsnummer | 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 | Lager | 1 | 1 | 2720 ​​| 9096 | 2720 ​​| 9096 |+-----------------------+---------------+------- -----+--------------------+------------------------------- ----------------------+---------------------- --------------------+----------------------------- -----------------------+--------------------- ----------------------------+

Sie können auch @partition_number verwenden dasselbe mit Partitionen zu tun.

Die Stärke der Komprimierung kann erheblich variieren

Der Grad der Komprimierung hängt von den Daten und der Art der Komprimierung ab.

ROW Die Komprimierung entfernt beispielsweise nicht benötigte Bytes aus den Spaltenwerten, indem sie in einem Format mit variabler Länge gespeichert werden. PAGE Die Komprimierung hingegen speichert die sich wiederholenden Werte nur einmal pro Seite und setzt den Zeiger von den entsprechenden Spalten innerhalb der Seite.

Manchmal stellen Sie möglicherweise fest, dass das Komprimieren eines Objekts seine Größe nicht immer verringert und in einigen Fällen sogar erhöht seine Größe.

Dies könnte passieren, wenn Ihre Spalten einen Datentyp verwenden, der nicht von der Komprimierung profitiert.

Außerdem reduziert die Zeilenkomprimierung den Metadaten-Overhead, aber in einigen Fällen kann der Overhead größer sein als beim alten Speicherformat.

Wenn Ihre Daten aufgrund ihres Datentyps nicht von der Komprimierung profitieren, führt der Overhead wahrscheinlich eher zu einer Erhöhung als zu einer Verringerung der Speicheranforderungen.

Abweichungen in der Komprimierungsgröße hängen jedoch auch von den tatsächlichen Daten ab. Zum Beispiel, wenn Sie ein char(10) haben Spalte entfernt die Komprimierung alle nachgestellten Füllzeichen. Wenn Sie viele Zeilen mit abschließenden Füllzeichen haben, sollten Sie ein besseres Ergebnis erzielen, als wenn Sie keine (oder wenige) Zeilen mit abschließenden Füllzeichen haben.

Wie wird die Komprimierung geschätzt?

Wenn Sie sp_estimate_data_compression_savings ausführen , nimmt es eine Stichprobe der Daten und lädt sie dann in eine entsprechende Tabelle und einen entsprechenden Index, die in tempdb erstellt wurden . Die Tabelle oder der Index werden in tempdb erstellt wird dann auf die angeforderte Einstellung komprimiert und die geschätzten Komprimierungseinsparungen werden berechnet.

Wie genau ist es?

Sie erhalten möglicherweise gemischte Ergebnisse, wenn Sie sp_estimate_data_compression_savings verwenden .

Lassen Sie uns einen kleinen Test durchführen.

SELECT * INTO Warehouse.StockItemTransactions2
FROM Warehouse.StockItemTransactions;

EXEC sp_spaceused 'Warehouse.StockItemTransactions2'; 

Ergebnis (bei vertikaler Ausgabe):

| StockItemTransactions2rows | 236667 reserviert | 15944 KBDaten | 15800 KBIndexgröße | 8 KBungenutzt | 136 KB

Der sp_spaceused gespeicherte Prozedur zeigt uns den tatsächlich verwendeten Speicherplatz. In diesem Fall verwenden Daten 15.800 KB Speicherplatz.

Jetzt führe ich sp_estimate_data_compression_savings aus um zu sehen, welche Platzersparnis ich erhalte, wenn ich die Komprimierung auf diese Tabelle anwende.

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemTransactions2', 
    @index_id = NULL, 
    @partition_number = NULL, 
    @data_compression = 'ROW'; 

Ergebnis (bei vertikaler Ausgabe):

Objektname | StockItemTransactions2schema_name | Warehouseindex_id | 0Partitionsnummer | 1size_with_current_compression_setting(KB) | 15808size_with_requested_compression_setting(KB) | 9096sample_size_with_current_compression_setting(KB) | 15800sample_size_with_requested_compression_setting(KB) | 9096

Gemäß diesen Ergebnissen wird die Anwendung der Zeilenkomprimierung auf diese Tabelle ihre Größe von 15.808 KB auf eine geschätzte Größe von nur 9.096 KB reduzieren. Nicht so schlimm.

Lassen Sie uns nun die Zeilenkomprimierung auf diese Tabelle anwenden und dann sp_spaceused ausführen nochmal.

ALTER TABLE Warehouse.StockItemTransactions2
REBUILD WITH (DATA_COMPRESSION = ROW);

EXEC sp_spaceused 'Warehouse.StockItemTransactions2'; 

Ergebnis (bei vertikaler Ausgabe):

| StockItemTransactions2rows | 236667 reserviert | 9160 KBDaten | 9088 KBIndexgröße | 8 KB

Das tatsächliche Ergebnis liegt also sehr nahe am geschätzten Ergebnis.

In diesem Fall sp_estimate_data_compression_savings lieferte eine ziemlich genaue Schätzung des Endergebnisses.

Lassen Sie uns sp_estimate_data_compression_savings ausführen noch einmal, aber mit einem Komprimierungstyp von NONE .

EXEC sp_estimate_data_compression_savings 
    @schema_name = 'Warehouse', 
    @object_name = 'StockItemTransactions2', 
    @index_id = NULL, 
    @partition_number = NULL, 
    @data_compression = 'NONE'; 

Ergebnis:

Objektname | StockItemTransactions2schema_name | Warehouseindex_id | 0Partitionsnummer | 1size_with_current_compression_setting(KB) | 9096size_with_requested_compression_setting(KB) | 15808sample_size_with_current_compression_setting(KB) | 9096sample_size_with_requested_compression_setting(KB) | 15808

Dies sagt uns, was passieren würde, wenn wir wieder keine Komprimierung verwenden würden.

In diesem Fall zeigt es uns genau dieselbe Zahl (15.808 KB) an, die es uns vor der Anwendung der Komprimierung angezeigt hat, was, wie Sie sich erinnern werden, ziemlich nahe an der tatsächlichen Größe (15.800 KB) lag, die von sp_spaceused Verfahren.

Lassen Sie es uns also noch einmal ausführen und finden Sie es heraus.

ALTER TABLE Warehouse.StockItemTransactions2
REBUILD WITH (DATA_COMPRESSION = NONE);

EXEC sp_spaceused 'Warehouse.StockItemTransactions2'; 

Ergebnis (bei vertikaler Ausgabe):

| StockItemTransactions2rows | 236667 reserviert | 15880 KBDaten | 15800 KBIndexgröße | 8 KBungenutzt | 72 KB

Also wieder sp_estimate_data_compression_savings war fast genau richtig.

Dies ist jedoch nur ein einfacher Test. Andere Tests könnten Schätzungen zurückgeben, die weit davon entfernt sind. Ich habe Geschichten über sp_estimate_data_compression_savings gelesen Es werden völlig ungenaue Ergebnisse zurückgegeben, aber das habe ich selbst noch nicht erlebt.

Daher scheint sp_estimate_data_compression_savings kann in denselben Fällen eine genaue Schätzung liefern, in anderen weniger.

Sie müssen entscheiden, wie viel Vertrauen Sie in diese gespeicherte Prozedur setzen möchten. In jedem Fall sollten Sie wahrscheinlich einen Test in Ihrer Entwicklungs- oder Testumgebung durchführen, bevor Sie die Komprimierung in der Produktion anwenden.