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

Как да актуализирате статистиката на SQL Server за големи таблици

В предишната си статия разгледах накратко статистиката на базата данни, нейното значение и защо статистиката трябва да се актуализира. Освен това демонстрирах стъпка по стъпка процес за създаване на план за поддръжка на SQL Server за актуализиране на статистиката. В тази статия ще бъдат обяснени следните проблеми:1. Как да актуализирате статистиката с помощта на T-SQL команда. 2. Как да идентифицирате често актуализираните таблици с помощта на T-SQL и също как да актуализирате статистиката на таблици с често вмъквани/актуализирани/изтривани данни.

Актуализиране на статистическите данни с помощта на T-SQL

Можете да актуализирате статистиката с помощта на T-SQL скрипта. Ако искате да актуализирате статистиката с помощта на T-SQL или SQL Server студио за управление, имате нужда от ALTER база данни разрешение за базата данни. Вижте примера за T-SQL код, за да актуализирате статистиката на конкретна таблица:

АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА ..

Нека разгледаме примера за актуализиране на статистиката на OrderLines таблица на WideWorldImporters база данни. Следният скрипт ще направи това.

АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[OrderLines]

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

АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА <име_на_схема>.<име_на_таблица> <име_на_индекс>

В случай, че искате да актуализирате статистиката на IX_Sales_OrderLines_Perf_20160301_02 индекс на Поръчковите линии таблица, можете да изпълните следния скрипт:

АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[OrderLines] [IX_Sales_OrderLines_Perf_20160301_02]

Можете също да актуализирате статистиката на цялата база данни. Ако имате много малка база данни с малко таблици и малко количество данни, тогава можете да актуализирате статистиката на всички таблици в базата данни. Вижте следния скрипт:

ИЗПОЛЗВАЙТЕ wideworldimporters go EXEC Sp_updatestats

Актуализиране на статистическите данни за таблици с често вмъквани/актуализирани/изтривани данни

При големи бази данни планирането на задачата за статистика става сложно, особено когато имате само няколко часа за извършване на поддръжка на индекс, актуализиране на статистически данни и изпълнение на други задачи за поддръжка. Под голяма база данни имам предвид база данни, която съдържа хиляди таблици и всяка таблица съдържа хиляди редове. Например имаме база данни с име X. Тя има стотици таблици и всяка таблица има милиони редове. И само няколко таблици се актуализират често. Други таблици рядко се променят и имат много малко транзакции, извършени върху тях. Както споменах преди, за да поддържате производителността на базата данни на ниво, статистиката на таблицата трябва да е актуална. Така че създаваме план за поддръжка на SQL, за да актуализираме статистиката на всички таблици в базата данни X. Когато SQL сървърът актуализира статистическите данни на таблица, той използва значително количество ресурси, което може да доведе до проблем с производителността. Така че е необходимо много време за актуализиране на статистиката на стотици големи таблици и докато статистиката се актуализира, производителността на базата данни намалява значително. При такива обстоятелства винаги е препоръчително да актуализирате статистическите данни само за таблиците, които се актуализират често. Можете да следите промените в обема на данните или броя на редовете през времето, като използвате следните динамични изгледи за управление:1. sys.partitions предоставя информация за общия брой редове в таблица. 2. sys.dm_db_partition_stats предоставя информация за броя на редовете и броя на страниците на дял. 3. sys.dm_db_index_physical_stats предоставя информация за броя на редовете и страниците, плюс информация за фрагментацията на индекса и други. Подробностите за обема на данните са важни, но те не правят картината на дейността на базата данни пълна. Например, етапна таблица, която има почти същия брой записи, може да бъде изтрита от таблицата или да се вмъква в таблица всеки ден. Поради това моментна снимка на броя на редовете би предполагала, че таблицата е статична. Възможно е добавените и изтрити записи да имат много различни стойности, които променят силно разпределението на данните. В този случай автоматичното актуализиране на статистиката в SQL Server прави статистиката безсмислена. Следователно проследяването на броя на модификациите на таблица е много полезно. Това може да стане по следните начини:1. rowmodctr колона в sys.sysindexes 2. modified_count колона в sys.system_internals_partition_columns 3. modification_counter колона в sys.dm_db_stats_properties По този начин, както обясних по-рано, ако имате ограничено време за поддръжка на база данни, винаги е препоръчително да актуализирате статистиката само за таблиците с по-висока честота на промяна на данните (вмъкване / актуализиране / изтриване). За да направя това ефективно, създадох скрипт, който актуализира статистическите данни за „активните“ таблици. Скриптът изпълнява следните задачи:• Декларира необходимите параметри • Създава временна таблица с име #tempstatistics за съхраняване на името на таблицата, името на схемата и името на базата данни • Създава друга таблица с име #tempdatabase за съхраняване на името на базата данни. Първо, изпълнете следния скрипт, за да създадете две таблици:

ДЕКЛАРИРАНЕ @databasename VARCHAR(500) ДЕКЛАРИРАНЕ @i INT=0 ДЕКЛАРИРАНЕ @DBCOunt INT ДЕКЛАРИРАНЕ @SQLCOmmand NVARCHAR(max) ДЕКЛАРИРАНЕ @StatsUpdateCOmmand NVARCHAR(max) CREATE TABLE #CHARCHAR име на таблица (xma tempstatistics) (xma база данни tempstatistics(max) , schemaname VARCHAR(max) ) CREATE TABLE #tempdatabases (име на база данни VARCHAR(max)) INSERT INTO #tempdatabases (databasename) SELECT NAME FROM sys.databases WHERE database_id> 4 ORDER BY NAME

След това напишете while цикъл, за да създадете динамична SQL заявка, която итерира през всички бази данни и вмъква списък с таблици, които имат брояч на модификации по-голям от 200 в #tempstatistics маса. За да получа информация за промени в данните, използвам sys.dm_db_stats_properties . Проучете следния пример за код:

SET @DBCOunt=(SELECT Count(*) FROM #tempdatabases) WHILE ( @i <@DBCOunt) BEGIN DECLARE @DBName VARCHAR(max) SET @DBName=(SELECT TOP 1 databasename FROM #tempdatabases) SET @SQLCOmmand=' използвайте [' + @DBName + ']; изберете различен ''' + @DBName+ ''', a.TableName,a.SchemaName от (ИЗБЕРЕТЕ obj.name като TableName, b.name като SchemaName,obj.object_id, stat.name, stat.stats_id, last_updated, modification_counter FROM [' + @DBName+ '].sys.objects AS obj вътрешно присъединяване ['+ @DBName + '].sys.schemas b на obj.schema_id=b.schema_id INNER JOIN [' + @DBName+ '].sys.stats AS stat ON stat.object_id =obj.object_id CROSS APPLY [' + @DBName+'].sys.dm_db_stats_properties(stat.object_id, stat.stats_id) AS sp WHERE modification_counter> 200 и obj.name не е като ''sys%''и b.name не е като ''sys%'')a' INSERT INTO #tempstatistics (име на база данни, име на таблица, име на схема) EXEC Sp_executesql @SQLCOmmand

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

DECLARE @j INT=0 DECLARE @StatCount INT SET @StatCount =(SELECT Count(*) FROM #tempstatistics) WHILE @J <@StatCount BEGIN DECLARE @DatabaseName_Stats VARCHAR(max) DECLARE @Table_Stats VARECLARE @Table_Stats VAR Schema_Stats VARCHAR(max) DECLARE @StatUpdateCommand NVARCHAR(max) SET @DatabaseName_Stats=(SELECT TOP 1 databasename FROM #tempstatistics) SET @Table_Stats=(SELECT TOP 1 tablename FROM #tempstatistics) SET @Schema TOPname(Schema_Schema TOPname) ) SET @StatUpdateCommand='Актуализиране на статистиката [' + @DatabaseName_Stats + '].[' + @Schema_Stats + '].[' + @Table_Stats + '] с пълно сканиране' EXEC Sp_executesql @StatUpdateCommand.DELETE FROM #tempstatistics WHERE име на база данни =@DatabaseName_Stats AND tablename =@Table_Stats AND schemaname =@Schema_Stats END SET @[email protected] + 1 DELETE FROM #tempdatabases WHERE име на база данни =@pre>DBName END
 След като изпълнението на скрипта приключи, всички временни таблици ще бъдат премахнати.

ИЗБЕРЕТЕ * ОТ #tempstatistics ОТПУСКАТЕ ТАБЛИЦА #tempdatabases ОТПУСКАТЕ ТАБЛИЦА #tempstatistics

Целият скрипт ще се появи, както следва:

--задайте броя на CREATE PROCEDURE Statistics_maintenance КАТО BEGIN DECLARE @databasename VARCHAR(500) DECLARE @i INT=0 ДЕКЛАРИРАНЕ @DBCOunt INT DECLARE @SQLCOmmand NVARCHAR(max) ДЕКЛАРИРАНЕ @COmmandUpdate база данни (StatsUpdate) VARCHAR(max), име на таблица VARCHAR(max), schemaname VARCHAR(max) ) CREATE TABLE #tempdatabases (име на база данни VARCHAR(max)) INSERT INTO #tempdatabases (име на база данни) SELECT NAME FROM sys.databases WHERE databaseORD_id> BY4 DBCOunt=(SELECT Count(*) FROM #tempdatabases) WHILE ( @i <@DBCOunt) BEGIN DECLARE @DBName VARCHAR(max) SET @DBName=(SELECT TOP 1 databasename FROM #tempdatabases) SET @SQLCOmmand=' use [' + @DBName + ']; изберете различен ''' + @DBName+ ''', a.TableName,a.SchemaName от (ИЗБЕРЕТЕ obj.name като TableName, b.name като SchemaName,obj.object_id, stat.name, stat.stats_id, last_updated, modification_counter FROM [' + @DBName+ '].sys.objects AS obj вътрешно присъединяване ['+ @DBName + '].sys.schemas b на obj.schema_id=b.schema_id INNER JOIN [' + @DBName+ '].sys.stats AS stat ON stat.object_id =obj.object_id CROSS APPLY [' + @DBName+'].sys.dm_db_stats_properties(stat.object_id, stat.stats_id) AS sp WHERE modification_counter> 200 и obj.name не е като ''sys%''и b.name не е като ''sys%'')a' INSERT INTO #tempstatistics (име на база данни, име на таблица, име на схема) EXEC Sp_executesql @SQLCOmmand DECLARE @j INT=0 ДЕКЛАРИРАНЕ @StatCount INT SET @StatCount =(SELECT Count(*) FROM #tempstatistics) WHILE @J <@StatCount BEGIN ДЕКЛАРИРАНЕ @DatabaseName_Stats VARCHAR(max) DECLARE @Table_Stats V ARCHAR(max) DECLARE @Schema_Stats VARCHAR(max) DECLARE @StatUpdateCommand NVARCHAR(max) SET @DatabaseName_Stats=(SELECT TOP 1 databasename FROM #tempstatistics) SET @Table_Stats=(SELECT TOP 1 tablestachename) TOP 1 schemaname FROM #tempstatistics) SET @StatUpdateCommand='Актуализиране на статистическите данни [' + @DatabaseName_Stats + '].[' + @Schema_Stats + '].[' + @Table_Stats + '] с пълно сканиране' EXEC @ Sp_executeleUp @SampextaleUp l. @sqldat.com + 1 DELETE FROM #tempstatistics WHERE име на база данни =@DatabaseName_Stats AND tablename =@Table_Stats AND schemaname =@Schema_Stats END SET @[email protected] + 1 DELETE FROM #tempdatabase s WHERE име на база данни =@DBName END SELECT * FROM #tempstatistics DROP TABLE #tempdatabases DROP TABLE #tempstatistics END

Можете също така да автоматизирате този скрипт, като създадете задание на SQL Server Agent, което ще го изпълни в насрочено време. По-долу е дадена стъпка по стъпка инструкции за автоматизиране на тази работа.

Създаване на SQL задание

Първо, нека създадем SQL задание, за да автоматизираме процеса. За да направите това, отворете SSMS, свържете се с желания сървър и разгънете SQL Server Agent, щракнете с десния бутон върху Jobs и изберете Нова работа . В Нова работа диалогов прозорец, въведете желаното име в Име поле. Сега кликнете върху Стъпки опция от менюто в левия панел на Нова работа диалогов прозорец, след което щракнете върху Ново в Стъпките прозорец. В стъпката Нова работа диалогов прозорец, който се отваря, посочете желаното име в Име на стъпка поле. След това изберете Transact-SQL скрипт (T-SQL) в Тип падащо меню. След това изберете DBATools в База данни падащо меню и напишете следната заявка в текстовото поле на командата:

EXEC Statistics_maintenance

За да конфигурирате графика на заданието, щракнете върху Графици опция от менюто в Нова работа диалогов прозорец. Нов график за работа диалогов прозорец се отваря. В Име поле, посочете желаното име на график. В нашия пример искаме тази задача да се изпълнява всяка вечер в 1 часа сутринта, следователно в Случва се падащото поле в Честота раздел изберете Ежедневно . В Случва се веднъж в полето в Дневна честота раздел, въведете 01:00:00. Щракнете върху OK за да затворите Нов график за работа прозорец и след това щракнете върху OK отново в Нова работа диалогов прозорец, за да го затворите. Сега нека тестваме тази работа. Под SQL Server Agent щракнете с десния бутон върху Update_Statistics_Daily . В случай, че задачата е била изпълнена успешно, ще видите следния прозорец.

Резюме

В тази статия бяха разгледани следните проблеми:1. Как да актуализирате статистиката на таблици с помощта на T-SQL Script. 2. Как да получите информация за промените в обема на данните и честотата на промените в данните. 3. Как да създадете скрипта, който актуализира статистиката за активните таблици. 4. Как да създадете задание на агент на SQL Server за изпълнение на скрипта в насроченото време.


  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:низът за връзка не е валиден [87]

  2. Три лесни победи за производителност на SQL Server

  3. SQL Server Fuzzy Search с процент на съвпадение

  4. Fix Error Msg 4151 „Типът на първия аргумент за NULLIF не може да бъде константа NULL, защото типът на първия аргумент трябва да бъде известен“ в SQL Server

  5. Как да определите общия брой отворени/активни връзки в ms sql server 2005