Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL Server 2014 Инкрементална статистика

Бенджамин Неварез е независим консултант със седалище в Лос Анджелис, Калифорния, който е специализиран в настройката и оптимизацията на заявки на SQL Server. Той е автор на „SQL Server 2014 Query Tuning &Optimization“ и „Inside the SQL Server Query Optimizer“ и съавтор на „SQL Server 2012 Internals“. С повече от 20 години опит в релационни бази данни, Бенджамин е бил и лектор на много конференции на SQL Server, включително PASS Summit, SQL Server Connections и SQLBits. Блогът на Бенджамин може да бъде намерен на адрес http://www.benjaminnevarez.com и той може да бъде достигнат и по имейл на admin на benjaminnevarez dot com и в Twitter на @BenjaminNevarez.

Основен проблем с актуализирането на статистически данни в големи таблици в SQL Server е, че цялата таблица винаги трябва да бъде сканирана, например при използване на WITH FULLSCAN опция, дори ако са се променили само последните данни. Това е вярно и при използване на разделяне:дори само най-новият дял да се е променил от последния път, когато статистиката е била актуализирана, актуализирането на статистиката отново е необходимо, за да се сканира цялата таблица, включително всички дялове, които не са се променили. Инкременталната статистика, нова функция на SQL Server 2014, може да помогне с този проблем.

Използвайки инкрементални статистически данни, можете да актуализирате само дяла или дяловете, от които се нуждаете, и информацията за тези дялове ще бъде обединена със съществуващата информация, за да създадете окончателния статистически обект. Друго предимство на инкременталната статистика е, че процентът промени в данните, необходими за задействане на автоматична актуализация на статистиката, сега работи на ниво дял, което основно означава, че сега са необходими само 20% от променените редове (промени в водещата статистическа колона) на дял. За съжаление хистограмата все още е ограничена до 200 стъпки за целия статистически обект в тази версия на SQL Server.

Нека разгледаме пример за това как можете да актуализирате статистиката на ниво дял, за да проучите поведението му поне спрямо SQL Server 2014 CTP2. Първо трябва да създадем разделена таблица, използвайки базата данни 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

Забележка:За подробности относно разделянето на дялове и CREATE PARTITION FUNCTION / SCHEME изявления, моля, вижте Разделени таблици и индекси в Books Online.

В момента имаме данни за попълване на 12 дяла. Нека започнем, като първо попълним само 11.

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

Ако е необходимо, можете да използвате следния оператор, за да проверите съдържанието на дяловете:

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

Нека създадем инкрементален статистически обект, използвайки CREATE STATISTICS изявление с новия INCREMENTAL клауза, зададена на ON (OFF е по подразбиране):

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

Можете също така да създавате постепенна статистика, докато създавате индекс, като използвате новия STATISTICS_INCREMENTAL клауза на CREATE INDEX изявление.

Можете да проверите създадения статистически обект с помощта на DBCC :

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

Освен всичко друго, ще забележите, че хистограмата има 200 стъпки (само последните 3 са показани тук):

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 2008-07-31 00:00:00,000 281 131 3

Първоначални резултати от DBCC

Така че вече имаме максималния брой стъпки в статистически обект. Какво ще се случи, ако добавите данни към нов дял? Нека добавим данни към дял 12:

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

Сега актуализираме статистическия обект, използвайки следния израз:

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

Обърнете внимание на новия синтаксис, определящ дяла, където можете да посочите множество дялове, разделени със запетая. UPDATE STATISTICS оператор чете посочените дялове и след това обединява техните резултати със съществуващия статистически обект, за да изгради глобалната статистика. Обърнете внимание на RESAMPLE клауза; това е необходимо, тъй като статистическите данни за дяловете трябва да имат еднакви честоти на извадка, за да бъдат обединени, за да се изгради глобалната статистика. Въпреки че е сканиран само посоченият дял, можете да видите, че SQL Server е пренаредил хистограмата. Последните три стъпки вече показват данни за добавения дял. Можете също да сравните оригинала с новата хистограма за други незначителни разлики:

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 22.08.2008 00:00:00.000 229 43 7
200 2008-09-03 00:00:00,000 363 37 11

Резултати от DBCC след постепенната актуализация

Ако по някаква причина искате да деактивирате инкременталните статистически данни, можете да използвате следния израз, за ​​да се върнете към първоначалното поведение (или по желание просто пуснете статистическия обект и създадете нов).

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

След деактивиране на инкременталната статистика, опитът за актуализиране на дял, както е показано по-горе, ще върне следното съобщение за грешка:

Съобщение 9111, ниво 16, състояние 1
Актуализиране на СТАТИСТИКАТА НА ДЯЛОВЕТЕ Синтаксисът не се поддържа за ненарастващи статистики.

И накрая, можете също да активирате инкрементални статистически данни за вашите автоматични статистически данни на ниво база данни, ако е необходимо. Това изисква INCREMENTAL = ON клауза в ALTER DATABASE изявление и очевидно също изисква AUTO_CREATE_STATISTICS зададен на ON .


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Разтягане на база данни в SQL Server 2016 RTM

  2. Как да използвате GOTO в SQL Server

  3. Динамичният SQL резултати във временна таблица в SQL Съхранена процедура

  4. TABLOCK срещу TABLOCKX

  5. Как да четете и анализирате планове за изпълнение на SQL Server