В нашем предыдущем посте мы обсудили порог автоматического обновления статистики и пришли к выводу, что он может обеспечить оптимальную производительность в определенных рабочих нагрузках. Однако есть случаи, когда ручное обновление статистики может помочь еще больше улучшить производительность. В этом посте мы рассмотрим, как обнаружить устаревшую статистику в SQL Server.
Начиная с SQL Server 2005, SQL Server использует ColModCtr для отслеживания изменений в ведущем столбце статистики. К сожалению, эта информация не отображается через какую-либо DMV или системное представление в SQL Server 2005 или SQL Server 2008. Однако, начиная с SQL Server 2008 R2 (SP2), мы можем использовать представление sys.dm_db_stats_properties для получения подробной информации о статистике, включая изменения в ведущем столбце.
Для пользователей более старых версий SQL Server нам нужно полагаться на столбец rowmodctr, доступный в представлении sys.sysindexes. Важно отметить, что rowmodctr не полностью совместим с более ранними версиями SQL Server. В более ранних версиях Database Engine поддерживал счетчики модификаций на уровне строк, тогда как сейчас они поддерживаются на уровне столбцов. В результате столбец rowmodctr дает похожие, но не точные результаты по сравнению с более ранними версиями.
Вот запрос, который может дать оценку изменений в статистике:
SELECT
TableName = OBJECT_NAME(i.OBJECT_ID),
ObjectType = o.type_desc,
StatisticsName = i.[name],
StatisticsUpdateDate = STATS_DATE(i.OBJECT_ID, i.index_id),
RecordModified = si.rowmodctr,
NumberOfRecords = si.rowcnt
FROM
sys.indexes i
JOIN
sys.objects o ON i.OBJECT_ID = o.OBJECT_ID
JOIN
sys.sysindexes si ON i.OBJECT_ID = si.id AND i.index_id = si.indid
WHERE
o.TYPE <> 'S'
AND STATS_DATE(i.OBJECT_ID, i.index_id) IS NOT NULL
UNION ALL
SELECT
TableName = OBJECT_NAME(o.OBJECT_ID),
ObjectType = o.type_desc,
StatisticsName = s.name,
StatisticsUpdateDate = STATS_DATE(o.OBJECT_ID, s.stats_id),
RecordModified = si.rowmodctr,
NumberOfRecords = ir.rowcnt
FROM
sys.stats s
INNER JOIN
sys.objects o ON s.OBJECT_ID = o.OBJECT_ID
JOIN
sys.sysindexes si ON s.OBJECT_ID = si.id AND s.stats_id = si.indid
INNER JOIN
(SELECT id, rowcnt FROM sys.sysindexes WHERE indid IN (0, 1)) IR ON IR.id = o.OBJECT_ID
WHERE
o.TYPE <> 'S'
AND (s.auto_created = 1 OR s.user_created = 1)
AND STATS_DATE(o.OBJECT_ID, s.stats_id) IS NOT NULL
Используя этот запрос в качестве основы, мы можем определить изменения в статистике на основе рабочей нагрузки или типов выполняемых запросов. Это позволяет нам планировать обновление статистики в соответствующие интервалы, а не слепо обновлять все статистики.
Если вам понравился этот пост, пожалуйста, поставьте лайк на нашей странице в Facebook по адресу www.PracticalSqlDba.com.