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

Друг начин за преглед на автоматични актуализации на статистиката

Още през април писах за някои естествени методи в SQL Server, които могат да се използват за проследяване на автоматични актуализации на статистиката. Трите опции, които предоставих, бяха SQL Trace, Extended Events и моментни снимки на sys.dm_db_stats_properties. Въпреки че тези три опции остават жизнеспособни (дори в SQL Server 2014, въпреки че моята най-добра препоръка все още е XE), допълнителна опция, която забелязах при провеждането на някои тестове наскоро, е SQL Sentry Plan Explorer.

Много от вас използват Plan Explorer просто за четене на изпълнявани планове, което е страхотно. Той има много предимства пред Management Studio, когато става въпрос за преглед на планове – от малки неща, като възможността да сортирате най-добрите оператори и лесно да виждате проблеми с оценката на кардиналността, до по-големи предимства, като обработка на сложни и големи планове и възможност за избор на един изявление в рамките на партида за по-лесен преглед на плана. Но зад визуалните елементи, които улесняват дисекцията на планове, Plan Explorer предлага също възможност за изпълнение на заявка и преглед на действителния план (вместо да го изпълнявате в Management Studio и да го запазвате). И на всичкото отгоре, когато стартирате плана от PE, има уловена допълнителна информация, която може да бъде полезна.

Нека започнем с демонстрацията, която използвах в скорошната си публикация, Как автоматичните актуализации на статистиката могат да повлияят на производителността на заявката. Започнах с базата данни AdventureWorks2012 и създадох копие на таблицата SalesOrderHeader с над 200 милиона реда. Таблицата има клъстериран индекс на SalesOrderID и неклъстериран индекс на CustomerID, OrderDate, SubTotal. [Отново:ако ще правите повторни тестове, направете резервно копие на тази база данни в този момент, за да си спестите известно време.] Първо проверих текущия брой редове в таблицата и броя на редовете, които ще трябва да се променят за да извикате автоматична актуализация:

SELECT
OBJECT_NAME([p].[object_id]) [TableName],
[si].[name] [IndexName],
[au].[type_desc] [Type],
[p].[rows] [RowCount],
([p].[rows]*.20) + 500 [UpdateThreshold],
[au].total_pages [PageCount],
(([au].[total_pages]*8)/1024)/1024 [TotalGB]
FROM [sys].[partitions] [p]
JOIN [sys].[allocation_units] [au] ON [p].[partition_id] = [au].[container_id]
JOIN [sys].[indexes] [si] on [p].[object_id] = [si].object_id and [p].[index_id] = [si].[index_id]
WHERE [p].[object_id] = OBJECT_ID(N'Sales.Big_SalesOrderHeader');


Big_SalesOrderHeader Информация за CIX и NCI

Проверих и текущата заглавка на статистиката за индекса:

DBCC SHOW_STATISTICS ('Sales.Big_SalesOrderHeader',[IX_Big_SalesOrderHeader_CustomerID_OrderDate_SubTotal]);


Статистика на NCI:в началото

Съхранената процедура, която използвам за тестване, вече е създадена, но за пълнота кодът е посочен по-долу:

CREATE PROCEDURE Sales.usp_GetCustomerStats
@CustomerID INT,
@StartDate DATETIME,
@EndDate DATETIME
AS
BEGIN
  SET NOCOUNT ON;
 
  SELECT CustomerID, DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate), COUNT([SalesOrderID]) as Computed
    FROM [Sales].[Big_SalesOrderHeader]
    WHERE CustomerID = @CustomerID
    AND OrderDate BETWEEN @StartDate and @EndDate
    GROUP BY CustomerID, DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)
    ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate);
END

Преди това или стартирах сесия за проследяване или разширени събития, или настроих своя метод за моментна снимка sys.dm_db_stats_properties към таблица. За този пример просто изпълних горепосочената съхранена процедура няколко пъти:

EXEC Sales.usp_GetCustomerStats 11331, '2012-08-01 00:00:00.000', '2012-08-31 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 11330, '2013-01-01 00:00:00.000', '2013-01-31 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 11506, '2012-11-01 00:00:00.000', '2012-11-30 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 17061, '2013-01-01 00:00:00.000', '2013-01-31 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 11711, '2013-03-01 00:00:00.000', '2013-03-31 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 15131, '2013-02-01 00:00:00.000', '2013-02-28 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 29837, '2012-10-01 00:00:00.000', '2012-10-31 23:59:59.997'
GO
EXEC Sales.usp_GetCustomerStats 15750, '2013-03-01 00:00:00.000', '2013-03-31 23:59:59.997'
GO

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

SELECT
OBJECT_NAME([st].[objectid]),
[st].[text],
[qs].[execution_count],
[qs].[creation_time],
[qs].[last_execution_time],
[qs].[min_worker_time],
[qs].[max_worker_time],
[qs].[min_logical_reads],
[qs].[max_logical_reads],
[qs].[min_elapsed_time],
[qs].[max_elapsed_time],
[qp].[query_plan]
FROM [sys].[dm_exec_query_stats] [qs]
CROSS APPLY [sys].[dm_exec_sql_text]([qs].plan_handle) [st]
CROSS APPLY [sys].[dm_exec_query_plan]([qs].plan_handle) [qp]
WHERE [st].[text] LIKE '%usp_GetCustomerStats%'
AND OBJECT_NAME([st].[objectid]) IS NOT NULL;


Информация за кеша за планиране за SP:В началото


План за заявка за съхранена процедура, използвайки SQL Sentry Plan Explorer

Планът е създаден на 29.09.2014 23:23.01.

След това добавих 61 милиона реда към таблицата, за да обезсиля текущата статистика и след като вмъкването приключи, проверих броя на редовете:


Big_SalesOrderHeader Информация за CIX и NCI:След вмъкване на 61 милиона редове

Преди да стартирам отново съхранената процедура, проверих, че броят на изпълнението не се е променил, че времето за създаване все още е 2014-09-29 23:23.01 за плана и че статистиката не се е актуализирала:


Информация за кеш на плана за SP:Веднага след вмъкване


NCI статистика:след вмъкване

Сега, в предишната публикация в блога, изпълних изявлението в Management Studio, но този път изпълних заявката директно от Plan Explorer и заснех действителния план чрез PE (опция, оградена в червено на изображението по-долу).


Изпълнете съхранена процедура от Plan Explorer

Когато изпълните изявление от PE, трябва да въведете екземпляра и базата данни, към които искате да се свържете, и след това ще бъдете уведомени, че заявката ще се изпълни и действителният план ще бъде върнат, но резултатите няма да бъдат върнати. Имайте предвид, че това е различно от Management Studio, където виждате резултатите.

След като стартирах съхранената процедура, в изхода не само получавам плана, но виждам какви оператори са били изпълнени:


Планирайте изход на Explorer след изпълнение SP (след вмъкване)

Това е доста готино… освен че виждам оператора, изпълнен в съхранената процедура, виждам и актуализациите на статистиката, точно както направих, когато заснех актуализации с помощта на разширени събития или SQL Trace. Заедно с изпълнението на оператора, можем също да видим информация за процесора, продължителността и IO. Сега – предупреждението тук е, че мога да видя тази информация if Изпълнявам изявлението, което извиква актуализацията на статистиката от Plan Explorer. Това вероятно няма да се случва често във вашата производствена среда, но може да видите това, когато правите тестване (защото се надяваме, че тестването ви не включва само изпълнение на заявки SELECT, но включва и заявки INSERT/UPDATE/DELETE точно както бихте направили вижте при нормално натоварване). Въпреки това, ако наблюдавате средата си с инструмент като SQL Sentry, може да видите тези актуализации в Top SQL стига да надвишават прага за събиране на Top SQL. SQL Sentry има прагове по подразбиране, които заявките трябва да надхвърлят, преди да бъдат уловени като най-добрия SQL (например продължителността трябва да надвишава пет (5) секунди), но можете да ги промените и да добавите други прагове, като например четения. В този пример само за тестови цели , промених моя праг за минимална продължителност на най-добрия SQL на 10 милисекунди и моя праг за четене на 500 и SQL Sentry успя да улови някои от актуализациите на статистиката:


Актуализации на статистиката, заснети от SQL Sentry

Въпреки това, дали мониторингът може да улови тези събития в крайна сметка ще зависи от системните ресурси и количеството данни, които трябва да бъдат прочетени, за да се актуализира статистиката. Вашите актуализации на статистическите данни може да не надхвърлят тези прагове, така че може да се наложи да направите по-проактивно копаене, за да ги намерите.

Резюме

Винаги насърчавам администраторите на база данни да управляват проактивно статистиката – което означава, че има работа за редовно актуализиране на статистиката. Въпреки това, дори ако това задание се изпълнява всяка вечер (което не препоръчвам непременно), все пак е напълно възможно актуализациите на статистическите данни да се извършват автоматично през деня, тъй като някои таблици са по-нестабилни от други и имат голям брой модификации. Това не е необичайно и в зависимост от размера на таблицата и количеството на модификациите, автоматичните актуализации може да не пречат значително на потребителските заявки. Но единственият начин да разберете е да наблюдавате тези актуализации – независимо дали използвате собствени инструменти или инструменти на трети страни – за да можете да сте пред потенциалните проблеми и да ги адресирате, преди да ескалират.


  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, как да използвам SELECT

  2. Отстраняване на неизправност при опит за създаване на голям IMDB модел

  3. Забавление с компресия (columnstore) на много голяма маса – част 3

  4. Оценка на кардиналност за предикат върху израз COUNT

  5. Език за дефиниране на SQL данни