Вступление
Я получил запрос от одного из моих друзей, спрашивающий о том, когда использовать sp_updatestats и как часто его использовать. Чтобы ответить на его запрос, я решил написать несколько слов, связанных со статистикой. Я надеюсь, что это будет информативным для всех нас.
Использование объектов статистики
Все мы знаем о важности объекта статистики для составления эффективного плана выполнения оптимизатором. Если объект статистики не обновляется должным образом, это приводит к плохому плану выполнения и снижению производительности запроса.
Когда создан объект статистики
Когда мы создаем Индекс, объект Статистика создается автоматически и называется Статистикой Индекса . Эта статистика будет существовать до тех пор, пока существует индекс.
Во-вторых, при условии, что включена опция базы данных «Автоматическое создание статистики», которая по умолчанию включена, SQL Server будет создавать статистику в один столбец всякий раз, когда в предикате запроса используется столбец, который не является ведущим столбцом в существующем индексе (например, в условии поиска предложения WHERE или в условии JOIN). Мы называем это статистикой столбцов . Мы также можем использовать команду CREATE STATISTICS для создания статистики из одного или нескольких столбцов вручную.
Когда обновляется объект статистики
Когда мы вставляем / обновляем / удаляем записи из объектов таблицы, SQL Server автоматически вставляет / обновляет / удаляет соответствующие строки в индексе.
Но статистика не обновляется таким образом, здесь мы имеем в виду, что когда мы вставляем / обновляем / удаляем записи из объектов таблицы, индекс обновляется автоматически, а статистика — нет. Хотя опция Автообновление статистики базы данных включена.
Поэтому мы должны понимать, когда статистика обновляется. Это зависит от определенного порога громкости.
По мере изменения данных в наших таблицах статистика — вся статистика — будет обновляться на основе следующей формулы:
· Когда таблица без строк получает строку
· Когда 500 строк заменены на таблицу, которая меньше 500 строк
· При изменении 20% + 500 в таблице, содержащей более 500 строк
Каждый раз, когда мы изменяем запись в таблице, SQL Server отслеживает ее через столбец rcmodified в скрытой системной таблице. SQL Server 2005 отслеживал эту информацию в таблице sys.rowsetcolumns. В SQL Server 2008 (и более поздних версиях) sys.rowsetcolumns объединился с sys.syshobtcolumns и стал sys.sysrscols.
Когда мы создаем или перестраиваем (не реорганизуем, просто перестраиваем) индекс, SQL Server генерирует статистику с помощью FULLSCAN, то есть сканирует все строки таблицы, чтобы создать гистограмму, которая представляет распределение данных в ведущем столбце индекса. , Аналогично, SQL будет автоматически создавать статистику столбцов с полной выборкой.
Когда обновлять статистику вручную
Предположим, у нас есть объекты таблиц из 100 миллионов записей, и SQL-сервер собирается обновить объекты статистики, когда 20% записей из 100 миллионов записей выполняется с помощью вставки / обновления / удаления. Таким образом, нам приходится долго ждать обновления объекта статистики, и результатом является плохое создание плана выкупа сервером SQL. В этой ситуации мы должны обновить объект статистики вручную.
В тех случаях, когда мы знаем, что распределение данных в столбце «искажено», может потребоваться вручную обновить статистику с полной выборкой или создать набор отфильтрованных статистических данных, чтобы генерировать планы запросов хорошего качества.
Изучение статистики
sp_helpstats 'tbl_CUSTOMERDTLS', 'ALL' statistics_name statistics_keys --------------- ---------------- _WA_Sys_00000001_03BB8E22 CUSTID _WA_Sys_00000002_03BB8E22 CUSTNAME _WA_Sys_00000003_03BB8E22 TOTALSALES _WA_Sys_00000004_03BB8E22 GRADE IX_CUSTID_tbl_CUSTOMERDTLS CUSTID
Лучший подход
SELECT [sch].[name] + '.' + [so].[name] AS [TableName] , [si].[index_id] AS [Index ID] , [ss].[name] AS [Statistic] , STUFF(( SELECT ', ' + [c].[name] FROM [sys].[stats_columns] [sc] JOIN [sys].[columns] [c] ON [c].[column_id] = [sc].[column_id] AND [c].[object_id] = [sc].[OBJECT_ID] WHERE [sc].[object_id] = [ss].[object_id] AND [sc].[stats_id] = [ss].[stats_id] ORDER BY [sc].[stats_column_id] FOR XML PATH('') ), 1, 2, '') AS [ColumnsInStatistic] , [ss].[auto_Created] AS [WasAutoCreated] , [ss].[user_created] AS [WasUserCreated] , [ss].[has_filter] AS [IsFiltered] , [ss].[filter_definition] AS [FilterDefinition] , [ss].[is_temporary] AS [IsTemporary] FROM [sys].[stats] [ss] JOIN [sys].[objects] AS [so] ON [ss].[object_id] = [so].[object_id] JOIN [sys].[schemas] AS [sch] ON [so].[schema_id] = [sch].[schema_id] LEFT OUTER JOIN [sys].[indexes] AS [si] ON [so].[object_id] = [si].[object_id] AND [ss].[name] = [si].[name] WHERE [so].[object_id] = OBJECT_ID(N'tbl_CUSTOMERDTLS') ORDER BY [ss].[user_created] , [ss].[auto_created] , [ss].[has_filter]; GO
В следующей версии мы поговорим об этом подробнее.
Надеюсь, вам понравится.