Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Statistiche incrementali di SQL Server 2014

Benjamin Nevarez è un consulente indipendente con sede a Los Angeles, California, specializzato nell'ottimizzazione e nell'ottimizzazione delle query di SQL Server. È autore di "SQL Server 2014 Query Tuning &Optimization" e "Inside the SQL Server Query Optimizer" e coautore di "SQL Server 2012 Internals". Con oltre 20 anni di esperienza nei database relazionali, Benjamin è stato anche relatore in molte conferenze su SQL Server, tra cui il PASS Summit, SQL Server Connections e SQLBits. Il blog di Benjamin può essere trovato su http://www.benjaminnevarez.com e può anche essere raggiunto via e-mail all'indirizzo admin di benjaminnevarez dot com e su Twitter all'indirizzo @BenjaminNevarez.

Un grosso problema con l'aggiornamento delle statistiche in tabelle di grandi dimensioni in SQL Server è che l'intera tabella deve sempre essere scansionata, ad esempio quando si utilizza WITH FULLSCAN opzione, anche se sono stati modificati solo i dati recenti. Questo vale anche quando si utilizza il partizionamento:anche se solo la partizione più recente è stata modificata dall'ultimo aggiornamento delle statistiche, è necessario aggiornare nuovamente le statistiche per eseguire la scansione dell'intera tabella, comprese tutte le partizioni che non sono state modificate. Le statistiche incrementali, una nuova funzionalità di SQL Server 2014, possono aiutare con questo problema.

Usando le statistiche incrementali puoi aggiornare solo la partizione o le partizioni di cui hai bisogno e le informazioni su queste partizioni verranno unite alle informazioni esistenti per creare l'oggetto statistico finale. Un altro vantaggio delle statistiche incrementali è che la percentuale di modifiche ai dati richiesta per attivare un aggiornamento automatico delle statistiche ora funziona a livello di partizione, il che significa sostanzialmente che ora è richiesto solo il 20% delle righe modificate (modifiche nella colonna principale delle statistiche) per partizione. Sfortunatamente l'istogramma è ancora limitato a 200 passaggi per l'intero oggetto statistiche in questa versione di SQL Server.

Esaminiamo un esempio di come aggiornare le statistiche a livello di partizione per esplorarne il comportamento almeno a partire da SQL Server 2014 CTP2. Per prima cosa dobbiamo creare una tabella partizionata utilizzando il database 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

Nota:per dettagli sul partizionamento e su CREATE PARTITION FUNCTION / SCHEME fare riferimento a Tabelle e indici partizionati nella documentazione in linea.

Al momento disponiamo di dati per popolare 12 partizioni. Cominciamo col popolarne prima solo 11.

INSERT INTO dbo.TransactionHistory
SELECT * FROM Production.TransactionHistory
WHERE TransactionDate < '2008-08-01';

Se necessario, è possibile utilizzare la seguente istruzione per esaminare il contenuto delle partizioni:

SELECT * FROM sys.partitions
  WHERE object_id = OBJECT_ID('dbo.TransactionHistory');

Creiamo un oggetto di statistica incrementale usando il CREATE STATISTICS dichiarazione con il nuovo INCREMENTAL clausola impostata su ON (OFF è l'impostazione predefinita):

CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) 
  WITH FULLSCAN, INCREMENTAL = ON;

Puoi anche creare statistiche incrementali mentre crei un indice usando il nuovo STATISTICS_INCREMENTAL clausola del CREATE INDEX dichiarazione.

Puoi ispezionare l'oggetto delle statistiche creato usando DBCC :

DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);

Tra l'altro, noterai che l'istogramma ha 200 passi (solo gli ultimi 3 mostrati qui):

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

Risultati DBCC iniziali

Quindi abbiamo già il massimo di passaggi in un oggetto di statistica. Cosa accadrebbe se aggiungi dati a una nuova partizione? Aggiungiamo i dati alla partizione 12:

INSERT INTO dbo.TransactionHistory 
SELECT * FROM Production.TransactionHistory 
WHERE TransactionDate >= '2008-08-01';

Ora aggiorniamo l'oggetto statistiche usando la seguente istruzione:

UPDATE STATISTICS dbo.TransactionHistory(incrstats) 
  WITH RESAMPLE ON PARTITIONS(12);

Nota la nuova sintassi che specifica la partizione, dove puoi specificare più partizioni, separate da virgola. Il UPDATE STATISTICS legge le partizioni specificate e quindi unisce i loro risultati con l'oggetto statistico esistente per creare le statistiche globali. Nota il RESAMPLE clausola; questo è necessario poiché le statistiche di partizione devono avere le stesse frequenze di campionamento per essere unite per creare le statistiche globali. Sebbene sia stata analizzata solo la partizione specificata, è possibile notare che SQL Server ha riorganizzato l'istogramma. Gli ultimi tre passaggi ora mostrano i dati per la partizione aggiunta. Puoi anche confrontare l'originale con il nuovo istogramma per altre differenze minori:

RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS
197 31-07-2008 00:00:00.000 150 131 2
198 12-08-2008 00:00:00.000 300 36 9
199 22-08-2008 00:00:00.000 229 43 7
200 2008-09-03 00:00:00.000 363 37 11

Risultati DBCC dopo l'aggiornamento incrementale

Se per qualsiasi motivo desideri disabilitare le statistiche incrementali, puoi utilizzare la seguente istruzione per tornare al comportamento originale (o facoltativamente semplicemente rilasciare l'oggetto statistiche e crearne uno nuovo).

UPDATE STATISTICS dbo.TransactionHistory(incrstats) 
  WITH FULLSCAN, INCREMENTAL = OFF;

Dopo aver disabilitato le statistiche incrementali provando ad aggiornare una partizione come mostrato in precedenza verrà restituito il seguente messaggio di errore:

Msg 9111, livello 16, stato 1
UPDATE STATISTICS ON PARTITIONS la sintassi non è supportata per le statistiche non incrementali.

Infine, puoi anche abilitare le statistiche incrementali per le tue statistiche automatiche a livello di database, se necessario. Ciò richiede INCREMENTAL = ON clausola nel ALTER DATABASE istruzione e ovviamente richiede anche AUTO_CREATE_STATISTICS impostato su ON .