Benjamin Nevarez jest niezależnym konsultantem z Los Angeles w Kalifornii, który specjalizuje się w dostrajaniu i optymalizacji zapytań SQL Server. Jest autorem „SQL Server 2014 Query Tuning &Optimization” i „Inside the SQL Server Query Optimizer” oraz współautorem „SQL Server 2012 Internals”. Mając ponad 20-letnie doświadczenie w relacyjnych bazach danych, Benjamin był również prelegentem na wielu konferencjach poświęconych SQL Server, w tym PASS Summit, SQL Server Connections i SQLBits. Blog Benjamina można znaleźć na http://www.benjaminnevarez.com i można się z nim również skontaktować przez e-mail na adres admin na benjaminnevarez dot com i na Twitterze na @BenjaminNevarez.
Głównym problemem związanym z aktualizacją statystyk w dużych tabelach w SQL Server jest to, że zawsze musi być skanowana cała tabela, na przykład przy użyciu WITH FULLSCAN
opcja, nawet jeśli zmieniły się tylko ostatnie dane. Odnosi się to również do korzystania z partycjonowania:nawet jeśli tylko najnowsza partycja zmieniła się od czasu ostatniej aktualizacji statystyk, ponowne zaktualizowanie statystyk wymagało przeskanowania całej tabeli, w tym wszystkich partycji, które się nie zmieniły. Statystyki przyrostowe, nowa funkcja SQL Server 2014, mogą pomóc w rozwiązaniu tego problemu.
Używając statystyk przyrostowych, możesz aktualizować tylko potrzebną partycję lub partycje, a informacje o tych partycjach zostaną połączone z istniejącymi informacjami w celu utworzenia ostatecznego obiektu statystyki. Inną zaletą statystyk przyrostowych jest to, że procent zmian danych wymaganych do wyzwolenia automatycznej aktualizacji statystyk działa teraz na poziomie partycji, co w zasadzie oznacza, że teraz wymagane jest tylko 20% zmienionych wierszy (zmiany w wiodącej kolumnie statystyk) na partycję. Niestety histogram jest nadal ograniczony do 200 kroków dla całego obiektu statystyk w tej wersji SQL Server.
Spójrzmy na przykład, w jaki sposób można zaktualizować statystyki na poziomie partycji, aby zbadać jej zachowanie przynajmniej od SQL Server 2014 CTP2. Najpierw musimy utworzyć tabelę partycjonowaną przy użyciu bazy danych AdventureWorks2012:
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
Uwaga:szczegółowe informacje na temat partycjonowania i CREATE PARTITION FUNCTION / SCHEME
oświadczenia znajdują się w sekcji Tabele i indeksy partycjonowane w Books Online.
Obecnie mamy dane do zapełnienia 12 partycji. Zacznijmy od wypełnienia tylko 11.
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
W razie potrzeby możesz użyć następującej instrukcji, aby sprawdzić zawartość partycji:
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
Stwórzmy przyrostowy obiekt statystyk za pomocą CREATE STATISTICS
oświadczenie z nowym INCREMENTAL
klauzula ustawiona na ON
(OFF
jest wartością domyślną):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
Możesz także tworzyć przyrostowe statystyki podczas tworzenia indeksu, korzystając z nowego STATISTICS_INCREMENTAL
klauzula CREATE INDEX
oświadczenie.
Możesz sprawdzić utworzony obiekt statystyk za pomocą DBCC
:
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
Między innymi zauważysz, że histogram ma 200 kroków (pokazane są tu tylko ostatnie 3):
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 |
Początkowe wyniki DBCC
Mamy więc już maksymalną liczbę kroków w obiekcie statystyk. Co się stanie, jeśli dodasz dane do nowej partycji? Dodajmy dane do partycji 12:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
Teraz aktualizujemy obiekt statystyk za pomocą następującej instrukcji:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
Zwróć uwagę na nową składnię określającą partycję, w której można określić wiele partycji oddzielonych przecinkiem. UPDATE STATISTICS
instrukcja odczytuje określone partycje, a następnie scala ich wyniki z istniejącym obiektem statystycznym w celu zbudowania statystyk globalnych. Zwróć uwagę na RESAMPLE
klauzula; jest to wymagane, ponieważ statystyki partycji muszą mieć te same częstotliwości próbkowania, aby mogły zostać scalone w celu zbudowania statystyk globalnych. Chociaż przeskanowano tylko określoną partycję, widać, że program SQL Server zmienił układ histogramu. Ostatnie trzy kroki pokazują teraz dane dla dodanej partycji. Możesz także porównać oryginał z nowym histogramem pod kątem innych drobnych różnic:
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 |
Wyniki DBCC po aktualizacji przyrostowej
Jeśli z jakiegoś powodu chcesz wyłączyć statystyki przyrostowe, możesz użyć następującej instrukcji, aby wrócić do pierwotnego zachowania (lub opcjonalnie po prostu usunąć obiekt statystyk i utworzyć nowy).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
Po wyłączeniu statystyk przyrostowych próba aktualizacji partycji, jak pokazano wcześniej, zwróci następujący komunikat o błędzie:
Msg 9111, Poziom 16, Stan 1Składnia AKTUALIZUJ STATYSTYKI NA PARTYCJACH nie jest obsługiwana w przypadku statystyk nieprzyrostowych.
W razie potrzeby można również włączyć statystyki przyrostowe dla statystyk automatycznych na poziomie bazy danych. Wymaga to INCREMENTAL = ON
klauzula w ALTER DATABASE
oświadczenie i oczywiście wymaga również AUTO_CREATE_STATISTICS
ustaw na ON
.