MSSQL: означает ли last_user_update, что индекс снижает производительность? - PullRequest
0 голосов
/ 01 июня 2009

Я написал запрос для поиска индексов, которые не используются в производственной среде, чтобы отбросить их, однако мне любопытно, является ли столбец last_user_update показателем того, что индекс был исключительно накладными расходами на обслуживание, в этом случае было бы хорошо удалить его, или индекс помог производительности оператора вставки / обновления / удаления, и в этом случае я бы не хотел его удалять. Ниже приведен запрос, который я хотел бы использовать:

DECLARE @DBInfo TABLE  
( database_id int, object_id int, tablename nvarchar(200), indexname nvarchar(200), lastactivity datetime)  

DECLARE @command VARCHAR(5000)  

SELECT @command = 'Use [' + '?' + '] SELECT  
database_id, o.object_id, o.name, i.name as indexname, max(lastactivity) as lastactivity
from (
    select database_id, object_id, index_id, max(last_user_seek) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    UNION ALL
    select database_id, object_id, index_id, max(last_user_scan) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    UNION ALL
    select database_id, object_id, index_id, max(last_user_lookup) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    /*UNION ALL
    select database_id, object_id, index_id, max(last_user_update) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id*/
) a
inner join sys.objects o on a.object_id = o.object_id
inner join sys.indexes i on i.object_id = a.object_id AND i.index_id = a.index_id
where database_id = db_id()
GROUP BY database_id, o.object_id, o.name, i.name
order by lastactivity'  
INSERT INTO @DBInfo  
   (database_id, object_id, tablename, indexname, lastactivity)  
EXEC sp_MSForEachDB @command  

SELECT db_name(database_id) as dbname, tablename, indexname, lastactivity FROM @DBInfo
where lastactivity < dateadd(day, -15, getdate()) or lastactivity is null
order by db_name(database_id), tablename, indexname 

Ответы [ 2 ]

2 голосов
/ 01 июня 2009

Столбец не имеет никакого реального значения при проверке неиспользуемых индексов.

Индекс может не иметь последних обновлений, но может быть очень полезным (например, чтобы избежать сканирования таблицы или охватить популярный запрос). Этот запрос говорит вам, как используется индекс:

SELECT
    o.name AS [object_name], 
    i.name AS index_name, 
    i.type_desc, 
    u.user_seeks, u.user_scans, 
    u.user_lookups, u.user_updates,
    o.type
FROM
    sys.indexes i
    JOIN
    sys.objects o ON i.[object_id] = o.[object_id]
    LEFT JOIN 
    sys.dm_db_index_usage_stats u ON i.[object_id] = u.[object_id] AND 
                                    i.index_id = u.index_id AND 
                                    u.database_id = DB_ID()
WHERE
    o.type IN ('U', 'V') AND
    i.name IS NOT NULL
ORDER BY 
    o.name, i.NAME;

Редактировать, после комментария:

Я предпочитаю столбцы user_seeks, user_scans, user_lookups and user_updates, которые сообщают мне, как используется индекс. К вашему сведению, я использовал приведенный выше запрос и включил столбцы «system_updates», но я получил ноль для всех значений (база данных SQL 2005, 50 ГБ или около того, где мы использовали это до хорошего эффекта)

С sys.dm_db_index_usage_stats

Счетчик user_updates указывает на уровень обслуживания по индексу вызвано вставкой, обновлением или удалением операции над базовой таблицей или Посмотреть. Вы можете использовать этот вид для определить, какие индексы используются только легко вашими приложениями. Вы можете также используйте вид, чтобы определить, какие индексы несут техническое обслуживание накладные расходы. Вы можете рассмотреть отбрасывая индексы, которые несут накладные расходы на техническое обслуживание, но не используются для запросов, или только нечасто используется для запросов.

Итак, последнее предложение подразумевает как использование, так и обновления

1 голос
/ 01 июня 2009

Если вас интересуют динамические свойства индексов - независимо от того, используются они или нет - возможно, вам лучше обратиться в DMV - Динамические административные представления, Они должны дать вам хорошую информацию о том, какие индексы используются и как часто.

Кроме того, есть один DMV, который фактически использует внутреннюю статистику оптимизатора запросов, чтобы предложить а) потенциально отсутствующие индексы, которые могут повысить производительность, и б) еще один, чтобы показать потенциально неиспользуемые индексы.

Имейте в виду - это динамические представления управления - они сбрасываются при каждой перезагрузке сервера, поэтому они не собирают данные в течение вечных периодов времени - только с момента вашего последнего сброса.

Марк

Поиск отсутствующих индексов:

SELECT  
    object_name(object_id), d.*, s.*
FROM
    sys.dm_db_missing_index_details d 
INNER JOIN 
    sys.dm_db_missing_index_groups g ON d.index_handle = g.index_handle
INNER JOIN 
    sys.dm_db_missing_index_group_stats s ON    g.index_group_handle = s.group_handle
WHERE   
    database_id = db_id()
ORDER BY  
    object_id

Найти неиспользуемые индексы:

DECLARE  @dbid INT

SELECT @dbid = DB_ID(DB_NAME())

SELECT   
    OBJECTNAME = OBJECT_NAME(I.OBJECT_ID),
    INDEXNAME = I.NAME,
    I.INDEX_ID
FROM     
    SYS.INDEXES I
JOIN 
    SYS.OBJECTS O ON I.OBJECT_ID = O.OBJECT_ID
WHERE    
    OBJECTPROPERTY(O.OBJECT_ID, 'IsUserTable') = 1
    AND I.INDEX_ID NOT IN (SELECT S.INDEX_ID
                            FROM SYS.DM_DB_INDEX_USAGE_STATS S
                            WHERE S.OBJECT_ID = I.OBJECT_ID
                                    AND I.INDEX_ID = S.INDEX_ID
                                    AND DATABASE_ID = @dbid)
ORDER BY 
    OBJECTNAME,
    I.INDEX_ID,
    INDEXNAME ASC
...