sql >> Database >  >> RDS >> Sqlserver

Incrementele statistieken voor SQL Server 2014

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 1
UPDATE 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 .


  1. MariaDB JSON_OBJECTAGG() uitgelegd

  2. Gegevensbestanden samenvoegen met Statistica, deel 2

  3. Hoe voer ik grote niet-blokkerende updates uit in PostgreSQL?

  4. TSQL Try / Catch binnen Transactie of vice versa?