Benjamin Nevarez is een onafhankelijke consultant gevestigd in Los Angeles, Californië, die gespecialiseerd is in het afstemmen en optimaliseren van SQL Server-query's. Hij is de auteur van "SQL Server 2014 Query Tuning &Optimization" en "Inside the SQL Server Query Optimizer" en co-auteur van "SQL Server 2012 Internals". Met meer dan 20 jaar ervaring in relationele databases is Benjamin ook spreker op vele SQL Server-conferenties, waaronder de PASS Summit, SQL Server Connections en SQLBits. Benjamins blog is te vinden op http://www.benjaminnevarez.com en hij is ook bereikbaar via e-mail op admin op benjaminnevarez dot com en op twitter op @BenjaminNevarez.
Een groot probleem bij het bijwerken van statistieken in grote tabellen in SQL Server is dat de hele tabel altijd gescand moet worden, bijvoorbeeld bij gebruik van de WITH FULLSCAN
optie, zelfs als alleen recente gegevens zijn gewijzigd. Dit geldt ook bij het gebruik van partitionering:zelfs als alleen de nieuwste partitie is gewijzigd sinds de laatste keer dat de statistieken zijn bijgewerkt, is het opnieuw nodig om de statistieken bij te werken om de hele tabel te scannen, inclusief alle partities die niet zijn gewijzigd. Incrementele statistieken, een nieuwe functie van SQL Server 2014, kunnen bij dit probleem helpen.
Met behulp van incrementele statistieken kunt u alleen de partitie of partities bijwerken die u nodig hebt en de informatie op deze partities wordt samengevoegd met de bestaande informatie om het uiteindelijke statistische object te maken. Een ander voordeel van incrementele statistieken is dat het percentage gegevenswijzigingen dat nodig is om een automatische update van statistieken te activeren nu werkt op partitieniveau, wat in feite betekent dat er nu slechts 20% van de gewijzigde rijen (wijzigingen in de leidende statistiekkolom) per partitie nodig is. Helaas is het histogram in deze versie van SQL Server nog steeds beperkt tot 200 stappen voor het gehele statistiekobject.
Laten we eens kijken naar een voorbeeld van hoe u statistieken op partitieniveau kunt bijwerken om het gedrag ervan ten minste vanaf SQL Server 2014 CTP2 te onderzoeken. Eerst moeten we een gepartitioneerde tabel maken met behulp van de AdventureWorks2012-database:
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
Opmerking:voor details over partitionering en de CREATE PARTITION FUNCTION / SCHEME
verklaringen verwijzen wij u naar gepartitioneerde tabellen en indexen in Books Online.
We hebben momenteel gegevens om 12 partities te vullen. Laten we beginnen door eerst slechts 11 in te vullen.
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
Indien nodig kunt u de volgende instructie gebruiken om de inhoud van de partities te inspecteren:
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
Laten we een incrementeel statistiekobject maken met behulp van de CREATE STATISTICS
statement met de nieuwe INCREMENTAL
clausule ingesteld op ON
(OFF
is de standaardinstelling):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
U kunt ook incrementele statistieken maken terwijl u een index maakt met behulp van de nieuwe STATISTICS_INCREMENTAL
clausule van de CREATE INDEX
verklaring.
U kunt het gemaakte statistiekobject inspecteren met DBCC
:
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
U zult onder andere merken dat het histogram 200 stappen heeft (alleen de laatste 3 worden hier getoond):
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
198 | 25-07-2008 00:00:00.000 | 187 | 100 | 2 |
199 | 27-07-2008 00:00:00.000 | 103 | 101 | 1 |
200 | 31-07-2008 00:00:00.000 | 281 | 131 | 3 |
Eerste DBCC-resultaten
We hebben dus al het maximum aantal stappen in een statistiekobject. Wat zou er gebeuren als u gegevens toevoegt aan een nieuwe partitie? Laten we gegevens toevoegen aan partitie 12:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
Nu werken we het statistiekobject bij met de volgende instructie:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
Let op de nieuwe syntaxis die de partitie specificeert, waar u meerdere partities kunt specificeren, gescheiden door komma's. De UPDATE STATISTICS
statement leest de gespecificeerde partities en voegt vervolgens hun resultaten samen met het bestaande statistische object om de globale statistieken op te bouwen. Let op de RESAMPLE
clausule; dit is vereist omdat partitiestatistieken dezelfde samplefrequenties moeten hebben om te worden samengevoegd om de globale statistieken op te bouwen. Hoewel alleen de opgegeven partitie is gescand, kunt u zien dat SQL Server het histogram heeft herschikt. De laatste drie stappen tonen nu gegevens voor de toegevoegde partitie. U kunt het origineel ook vergelijken met het nieuwe histogram voor andere kleine verschillen:
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
197 | 31-07-2008 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 | 03-09-2008 00:00:00.000 | 363 | 37 | 11 |
DBCC-resultaten na de incrementele update
Als u om welke reden dan ook de incrementele statistieken wilt uitschakelen, kunt u de volgende instructie gebruiken om terug te gaan naar het oorspronkelijke gedrag (of optioneel gewoon het statistische object laten vallen en een nieuwe maken).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
Na het uitschakelen van de incrementele statistieken zal het proberen om een partitie bij te werken zoals eerder getoond de volgende foutmelding geven:
Msg 9111, Level 16, State 1UPDATE STATISTICS ON PARTITIONS syntax wordt niet ondersteund voor niet-incrementele statistieken.
Ten slotte kunt u indien nodig ook incrementele statistieken voor uw automatische statistieken op databaseniveau inschakelen. Dit vereist de INCREMENTAL = ON
clausule in de ALTER DATABASE
statement en vereist uiteraard ook AUTO_CREATE_STATISTICS
ingesteld op ON
.