Benjamin Nevarez ist ein unabhängiger Berater mit Sitz in Los Angeles, Kalifornien, der sich auf die Optimierung und Optimierung von SQL Server-Abfragen spezialisiert hat. Er ist Autor von „SQL Server 2014 Query Tuning &Optimization“ und „Inside the SQL Server Query Optimizer“ und Co-Autor von „SQL Server 2012 Internals“. Mit mehr als 20 Jahren Erfahrung in relationalen Datenbanken war Benjamin auch Redner auf vielen SQL Server-Konferenzen, darunter PASS Summit, SQL Server Connections und SQLBits. Benjamins Blog ist unter http://www.benjaminnevarez.com zu finden und er kann auch per E-Mail unter admin at benjaminnevarez dot com und auf Twitter unter @BenjaminNevarez erreicht werden.
Ein großes Problem beim Aktualisieren von Statistiken in großen Tabellen in SQL Server ist, dass immer die gesamte Tabelle gescannt werden muss, zum Beispiel bei der Verwendung von WITH FULLSCAN
Option, auch wenn sich nur die letzten Daten geändert haben. Dies gilt auch bei Verwendung der Partitionierung:Selbst wenn sich seit der letzten Aktualisierung der Statistiken nur die neueste Partition geändert hat, ist eine erneute Aktualisierung der Statistiken erforderlich, um die gesamte Tabelle einschließlich aller Partitionen zu scannen, die sich nicht geändert haben. Inkrementelle Statistiken, eine neue Funktion von SQL Server 2014, können bei diesem Problem helfen.
Mithilfe inkrementeller Statistiken können Sie nur die Partition oder Partitionen aktualisieren, die Sie benötigen, und die Informationen zu diesen Partitionen werden mit den vorhandenen Informationen zusammengeführt, um das endgültige Statistikobjekt zu erstellen. Ein weiterer Vorteil inkrementeller Statistiken besteht darin, dass der Prozentsatz der Datenänderungen, der zum Auslösen einer automatischen Aktualisierung der Statistiken erforderlich ist, jetzt auf Partitionsebene funktioniert, was im Grunde bedeutet, dass jetzt nur noch 20 % der geänderten Zeilen (Änderungen in der führenden Statistikspalte) pro Partition erforderlich sind. Leider ist das Histogramm in dieser Version von SQL Server immer noch auf 200 Schritte für das gesamte Statistikobjekt beschränkt.
Sehen wir uns ein Beispiel an, wie Sie Statistiken auf Partitionsebene aktualisieren können, um ihr Verhalten zumindest ab SQL Server 2014 CTP2 zu untersuchen. Zuerst müssen wir eine partitionierte Tabelle mit der AdventureWorks2012-Datenbank erstellen:
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME) AS RANGE RIGHT FOR VALUES ( '20071001', '20071101', '20071201', '20080101', '20080201', '20080301', '20080401', '20080501', '20080601', '20080701', '20080801' ); GO CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO ( [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY] ); GO CREATE TABLE dbo.TransactionHistory ( TransactionID INT NOT NULL, -- not bothering with IDENTITY here ProductID INT NOT NULL, ReferenceOrderID INT NOT NULL, ReferenceOrderLineID INT NOT NULL DEFAULT (0), TransactionDate DATETIME NOT NULL DEFAULT (GETDATE()), TransactionType NCHAR(1) NOT NULL, Quantity INT NOT NULL, ActualCost MONEY NOT NULL, ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()), CONSTRAINT CK_TransactionType CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P')) ) ON TransactionsPS1 (TransactionDate); GO
Hinweis:Einzelheiten zur Partitionierung und zum CREATE PARTITION FUNCTION / SCHEME
Anweisungen finden Sie unter Partitionierte Tabellen und Indizes in Books Online.
Wir haben derzeit Daten, um 12 Partitionen zu füllen. Beginnen wir damit, zunächst nur 11 zu füllen.
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
Falls erforderlich, können Sie die folgende Anweisung verwenden, um den Inhalt der Partitionen zu überprüfen:
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
Lassen Sie uns mit CREATE STATISTICS
ein inkrementelles Statistikobjekt erstellen -Anweisung mit dem neuen INCREMENTAL
-Klausel auf ON
gesetzt (OFF
ist die Vorgabe):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
Sie können auch inkrementelle Statistiken erstellen, während Sie einen Index erstellen, indem Sie den neuen STATISTICS_INCREMENTAL
verwenden -Klausel des CREATE INDEX
Erklärung.
Sie können das erstellte Statistikobjekt mit DBCC
überprüfen :
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
Unter anderem werden Sie feststellen, dass das Histogramm 200 Schritte hat (hier werden nur die letzten 3 angezeigt):
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
198 | 2008-07-25 00:00:00.000 | 187 | 100 | 2 |
199 | 2008-07-27 00:00:00.000 | 103 | 101 | 1 |
200 | 2008-07-31 00:00:00.000 | 281 | 131 | 3 |
Erste DBCC-Ergebnisse
Wir haben also bereits das Maximum an Schritten in einem Statistikobjekt. Was würde passieren, wenn Sie Daten zu einer neuen Partition hinzufügen? Lassen Sie uns Daten zu Partition 12 hinzufügen:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
Jetzt aktualisieren wir das Statistikobjekt mit der folgenden Anweisung:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
Beachten Sie die neue Syntax zur Angabe der Partition, bei der Sie mehrere Partitionen angeben können, die durch Kommas getrennt sind. Die UPDATE STATISTICS
-Anweisung liest die angegebenen Partitionen und führt dann ihre Ergebnisse mit dem vorhandenen Statistikobjekt zusammen, um die globalen Statistiken zu erstellen. Beachten Sie das RESAMPLE
Klausel; Dies ist erforderlich, da Partitionsstatistiken dieselben Abtastraten haben müssen, um zusammengeführt zu werden, um die globalen Statistiken zu erstellen. Obwohl nur die angegebene Partition gescannt wurde, können Sie sehen, dass SQL Server das Histogramm neu angeordnet hat. Die letzten drei Schritte zeigen nun Daten für die hinzugefügte Partition. Sie können auch das Original mit dem neuen Histogramm auf andere kleinere Unterschiede vergleichen:
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
197 | 2008-07-31 00:00:00.000 | 150 | 131 | 2 |
198 | 2008-08-12 00:00:00.000 | 300 | 36 | 9 |
199 | 2008-08-22 00:00:00.000 | 229 | 43 | 7 |
200 | 2008-09-03 00:00:00.000 | 363 | 37 | 11 |
DBCC-Ergebnisse nach der inkrementellen Aktualisierung
Wenn Sie aus irgendeinem Grund die inkrementelle Statistik deaktivieren möchten, können Sie die folgende Anweisung verwenden, um zum ursprünglichen Verhalten zurückzukehren (oder optional einfach das Statistikobjekt löschen und ein neues erstellen).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
Nach dem Deaktivieren der inkrementellen Statistik wird beim Versuch, eine Partition wie zuvor gezeigt zu aktualisieren, die folgende Fehlermeldung zurückgegeben:
Msg 9111, Level 16, State 1UPDATE STATISTICS ON PARTITIONS-Syntax wird für nicht inkrementelle Statistiken nicht unterstützt.
Schließlich können Sie bei Bedarf auch inkrementelle Statistiken für Ihre automatischen Statistiken auf Datenbankebene aktivieren. Dazu ist INCREMENTAL = ON
erforderlich -Klausel in ALTER DATABASE
-Anweisung und erfordert natürlich auch AUTO_CREATE_STATISTICS
auf ON
setzen .