Published on

June 21, 2013

Как обнаружить устаревшую статистику в SQL Server

В нашем предыдущем посте мы обсудили порог автоматического обновления статистики и пришли к выводу, что он может обеспечить оптимальную производительность в определенных рабочих нагрузках. Однако есть случаи, когда ручное обновление статистики может помочь еще больше улучшить производительность. В этом посте мы рассмотрим, как обнаружить устаревшую статистику в 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.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.