sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Server 2014 inkrementell statistik

Benjamin Nevarez är en oberoende konsult baserad i Los Angeles, Kalifornien, som specialiserat sig på justering och optimering av SQL Server-frågor. Han är författare till "SQL Server 2014 Query Tuning &Optimization" och "Inside the SQL Server Query Optimizer" och medförfattare till "SQL Server 2012 Internals". Med mer än 20 års erfarenhet av relationsdatabaser har Benjamin även varit föredragshållare vid många SQL Server-konferenser, inklusive PASS Summit, SQL Server Connections och SQLBits. Benjamins blogg finns på http://www.benjaminnevarez.com och han kan också nås via e-post på admin på benjaminnevarez dot com och på twitter på @BenjaminNevarez.

Ett stort problem med att uppdatera statistik i stora tabeller i SQL Server är att hela tabellen alltid måste skannas, till exempel när du använder WITH FULLSCAN alternativet, även om bara de senaste uppgifterna har ändrats. Detta gäller också när du använder partitionering:även om bara den senaste partitionen hade ändrats sedan senaste gången statistiken uppdaterades, krävdes uppdatering av statistik igen för att skanna hela tabellen inklusive alla partitioner som inte ändrades. Inkrementell statistik, en ny SQL Server 2014-funktion, kan hjälpa till med detta problem.

Med hjälp av inkrementell statistik kan du bara uppdatera den eller de partitioner som du behöver och informationen om dessa partitioner kommer att slås samman med den befintliga informationen för att skapa det slutliga statistikobjektet. En annan fördel med inkrementell statistik är att procentandelen dataändringar som krävs för att utlösa en automatisk uppdatering av statistik nu fungerar på partitionsnivå vilket i princip innebär att nu endast 20% av raderna ändrade (ändringar i den ledande statistikkolumnen) per partition krävs. Tyvärr är histogrammet fortfarande begränsat till 200 steg för hela statistikobjektet i denna version av SQL Server.

Låt oss titta på ett exempel på hur du kan uppdatera statistik på partitionsnivå för att utforska dess beteende åtminstone från och med SQL Server 2014 CTP2. Först måste vi skapa en partitionerad tabell med hjälp av databasen 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

Obs:För detaljer om partitionering och CREATE PARTITION FUNCTION / SCHEME uttalanden hänvisas till Partitionerade tabeller och index i Books Online.

Vi har för närvarande data för att fylla 12 partitioner. Låt oss börja med att först fylla i endast 11.

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

Om det behövs kan du använda följande uttalande för att inspektera innehållet i partitionerna:

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

Låt oss skapa ett inkrementellt statistikobjekt med CREATE STATISTICS uttalande med den nya INCREMENTAL sats inställd på ON (OFF är standard):

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

Du kan också skapa inkrementell statistik samtidigt som du skapar ett index med den nya STATISTICS_INCREMENTAL satsen i CREATE INDEX uttalande.

Du kan inspektera det skapade statistikobjektet med DBCC :

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

Bland annat kommer du att märka att histogrammet har 200 steg (endast de 3 sista som visas här):

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

Initiala DBCC-resultat

Så vi har redan det maximala antalet steg i ett statistikobjekt. Vad skulle hända om du lägger till data till en ny partition? Låt oss lägga till data till partition 12:

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

Nu uppdaterar vi statistikobjektet med följande uttalande:

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

Notera den nya syntaxen som anger partitionen, där du kan ange flera partitioner, separerade med kommatecken. UPDATE STATISTICS uttalandet läser de angivna partitionerna och slår sedan samman deras resultat med det befintliga statistikobjektet för att bygga den globala statistiken. Notera RESAMPLE klausul; detta krävs eftersom partitionsstatistiken måste ha samma samplingsfrekvenser för att kunna slås samman för att skapa den globala statistiken. Även om endast den angivna partitionen skannades, kan du se att SQL Server har ordnat om histogrammet. De tre sista stegen visar nu data för den tillagda partitionen. Du kan också jämföra originalet med det nya histogrammet för andra mindre skillnader:

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-resultat efter den inkrementella uppdateringen

Om du av någon anledning vill inaktivera den inkrementella statistiken kan du använda följande uttalande för att gå tillbaka till det ursprungliga beteendet (eller eventuellt bara släppa statistikobjektet och skapa ett nytt).

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

Efter att ha inaktiverat den inkrementella statistiken kommer ett försök att uppdatera en partition som tidigare visat att returnera följande felmeddelande:

Msg 9111, Level 16, State 1
UPPDATERA STATISTIK PÅ PARTITIONER syntax stöds inte för icke-inkrementell statistik.

Slutligen kan du även aktivera inkrementell statistik för din automatiska statistik på databasnivå, om det behövs. Detta kräver INCREMENTAL = ON sats i ALTER DATABASE och kräver uppenbarligen också AUTO_CREATE_STATISTICS inställd på ON .


  1. Viloläge på Oracle:mappa String-egenskapen till CLOB-kolumnen

  2. Begäran misslyckades eller svarade inte tjänsten i tid?

  3. Beställ efter COUNT per värde

  4. Kontrollera Constraint i SQL