0

運用環境で使用されていないインデックスを削除するためにクエリを作成しましたが、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 
4

2 に答える 2

2

列は、未使用のインデックスをチェックする上で実際の意味はありません。

インデックスには最近の更新がない場合がありますが、それでも非常に便利です (たとえば、テーブル スキャンを回避したり、一般的なクエリをカバーしたりするため)。このクエリは、インデックスがどのように使用されているかを示します。

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、50Gb 程度のデータベースで、以前はこれを使用して効果がありました)。

からsys.dm_db_index_usage_stats

user_updates カウンターは、基になるテーブルまたはビューでの挿入、更新、または削除操作によって発生したインデックスのメンテナンスのレベルを示します。このビューを使用して、アプリケーションであまり使用されていないインデックスを特定できます。このビューを使用して、メンテナンスのオーバーヘッドが発生しているインデックスを特定することもできます。メンテナンスのオーバーヘッドが発生するが、クエリに使用されていないか、クエリに使用される頻度が低いインデックスを削除することを検討することをお勧めします。

したがって、最後の文は、使用状況と更新を確認することを意味します

于 2009-06-01T10:21:45.587 に答える
1

インデックスの動的なプロパティに興味がある場合は、使用されているかどうかに関係なく、DMV (動的管理ビュー) で問い合わせた方がよいでしょう。それらは、どのインデックスがどのくらいの頻度で使用されているかについての優れた情報を提供するはずです。

また、クエリ オプティマイザーの内部統計を実際に使用して、a) パフォーマンスを向上させるのに役立つ潜在的に欠落しているインデックスを提案する 1 つの DMV と、b) 未使用の可能性があるインデックスを表示する別の 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
于 2009-06-01T10:29:46.523 に答える