Wie kann ich feststellen, ob die Daten in einer SQL Server-Tabelle seitenkomprimiert sind?

8

Dies ist eine Folgefrage zu einer Frage, die ich gestern gestellt habe: Kann ich eine Masseneinfügung in eine leere, seitenkomprimierte Tabelle vornehmen und eine vollständige Komprimierung erhalten? Die Antwort auf diese Frage (umschrieben von Randi Vertongens ausgezeichneter Antwort) lautet Ja, erfordert jedoch, dass die Masseneinfügung eine Sperre auf Tabellenebene aufweist. Andernfalls nimmt die Masseneinfügung eine Sperre auf Zeilenebene vor und führt nur eine Zeilendatenkomprimierung durch. Dies wirft die Frage auf: Wie kann ich anschließend feststellen, welche Komprimierung angewendet wird?

Gehen Sie folgendermaßen vor, um zeilenkomprimierte Daten in einer theoretisch seitenkomprimierten Tabelle zu
erstellen : 1. Erstellen Sie eine Tabelle mit DATA_COMPRESSION=PAGEund aktivieren Sie nicht die sp_tableoptionOption "Tabellensperre beim Massenladen" für diese Tabelle.
2. Verwenden Sie bcp, um die Daten aus einer Flatfile in die neue Tabelle einzufügen, ohne jedoch die -h TABLOCKOption zum Sperren der Tabelle anzugeben .

Das Ergebnis ist eine Tabelle, in der die Daten auf Zeilenebene komprimiert werden (kleiner als eine nicht komprimierte Tabelle, aber größer als eine seitenkomprimierte Tabelle). Wenn Sie jedoch die sys.allocation_unitsKatalogtabelle überprüfen, wird die Datenkomprimierung als Seite angezeigt.

Die Frage

Wenn der Tisch Datenzuordnung für Seitenkomprimierung wie in diesem Szenario ist, was kann ich tun , wenn die , um herauszufinden , Daten in dieser Tabelle Seite komprimiert?

Caitlin M. Shaw
quelle
Auch für SQL 2016+ sollten Sie einen Clustered Columnstore-Index für Szenarien mit Massenladen und Komprimierung in Betracht ziehen.
David Browne - Microsoft

Antworten:

13

Um festzustellen, ob Datenseiten tatsächlich derzeit "PAGE" komprimiert sind, können Sie das undokumentierte DMF verwenden sys.dm_db_database_page_allocations(). Das is_page_compressedFeld enthält die gesuchten Informationen. Sie müssen den DETAILEDModus (dh den 5. Parameter) verwenden, sonst sind alle Werte in diesem Feld NULL.

Um es klar auszudrücken (basierend auf dem Wortlaut der Frage: "Was kann ich tun, um herauszufinden, ob die Daten in dieser Tabelle seitenkomprimiert sind?"), Ist dies kein Alles-oder-Nichts-Problem: Die Seitenkomprimierung wird angewendet Pro Datenseite können Sie also keine komprimierte, komprimierte oder eine beliebige Kombination dazwischen haben. Sie müssen sich also alle Seiten ansehen. Und nein, Sie können nicht unbedingt davon ausgehen, dass eine einzelne nicht seitenkomprimierte Seite dies anzeigt, REBUILDda eine nicht gefüllte Seite nicht komprimiert wird.

Zum Beispiel:

SELECT [is_page_compressed]
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED');

Das Folgende zeigt, dass die Datenseiten anfangs nicht seitenkomprimiert sind, sondern nach dem REBUILDVorgang:

USE [tempdb];

-- DROP TABLE dbo.CompressedHeap;
CREATE TABLE dbo.CompressedHeap
(
  ID INT IDENTITY(1, 1) NOT NULL,
  String sysname,
  [MaxLength] SMALLINT,
  [Type] VARCHAR(5)
) WITH (DATA_COMPRESSION = PAGE);


INSERT INTO dbo.CompressedHeap ([String], [MaxLength], [Type])
  SELECT col.[name], col.[max_length], obj.[type]
  FROM   master.sys.columns col
  CROSS JOIN master.sys.objects obj;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 394 pages


ALTER TABLE dbo.CompressedHeap REBUILD;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 179 pages
Solomon Rutzky
quelle
1
Genau das brauche ich, vielen Dank! Ich habe einige meiner tatsächlichen Tabellen überprüft und diejenigen, die ohne die Tabellensperre geladen wurden, haben 0% der Seiten komprimiert, während die neuen, die ich mit der Tabellensperre geladen habe, 99,8% der Seiten komprimiert haben (und weit weniger davon), genau wie Sie beschreiben.
Caitlin M. Shaw
0

Die Komprimierungsstufe finden Sie in der Datei sys.partitions dmv

SELECT t.name AS tablename,
       i.name AS indexname,
       p.data_compression_desc
FROM sys.tables AS t
INNER JOIN sys.indexes AS i
     ON t.object_id = i.object_id
INNER JOIN sys.partitions AS p
     ON i.object_id = p.object_id
        AND i.index_id = p.index_id;
Bob Klimes
quelle
1
Leider ist dies ein Szenario, in dem die tatsächliche Komprimierung auf den Datenseiten nicht den Angaben entspricht sys.partitions.
Caitlin M. Shaw
1
Hallo Bob (und @ CaitlinM.Shaw): Der Wert in sys.partitionssollte der angeforderte / ideale Datenkomprimierungstyp sein. Da sich dieser Wert jedoch nur auf Partitionsebene befindet, können weder der aktuelle Wert pro Seite noch der aktuelle Wert pro Zeile angezeigt werden, die beide innerhalb jeder Partition variieren können.
Solomon Rutzky
das ist gut zu wissen, danke
Bob Klimes