未使用的索引最佳做法


11

根据此查询,如果我发现总读取量很少(非常接近0或0,例如1或2),而用户更新量则较高或中等(我无法通过此查询找到插入或删除的内容),行数很大时,理论上我应该删除索引。

SELECT DISTINCT
    OBJECT_NAME(s.[object_id]) AS ObjectName
       , p.rows TableRows
       , i.name AS [INDEX NAME]
       , (user_seeks + user_scans + user_lookups) AS TotalReads
       , user_updates UserUpdates
FROM sys.dm_db_index_usage_stats s
    INNER JOIN sys.indexes i ON i.[object_id] = s.[object_id] 
        AND i.index_id = s.index_id 
    INNER JOIN sys.partitions p ON p.object_id = i.object_id
WHERE OBJECTPROPERTY(s.[object_id],'IsUserTable') = 1
       AND s.database_id = DB_ID()
       AND i.name IS NOT NULL
ORDER BY (user_seeks + user_scans + user_lookups) ASC

我想在这里交叉检查这种假设的准确性。例如,已经存在了一年以上但从未被读取过但已被高度更新的索引似乎是一个坏主意。是否存在这种假设无效的情况?

Answers:


15

自上次SQL Server重新启动以来,此DMV仅维护统计信息;视图被完全抹去,一切从头开始。

更重要的是,在重建该索引时,将删除该视图中任何特定索引的行(但在重组索引时,则不会删除该行)。如果您正在执行常规索引维护,则查看维护日志并查看您考虑删除的任何索引是否最近已重建可能会很有用。

因此,基于上次重启以来的低读取来做出决定(当上次重启可能是上周的补丁程序星期二更新或昨天的Service Pack时)可能不是明智的选择。或者在执行索引维护时,自上次重建以来。可能有一个仅每月一次,每季度一次或每年一次的报告,并且该报告是由重要且急躁的人运行的。

此外,对于将来您可能不知道的事情,可能会有一个索引-假设正在为税收季节准备一系列报告。

因此,我的建议是:

使用DMV 识别要删除的候选索引,但不要在泡沫中做出决定-您需要做些事来确定为什么删除索引之前可能存在一个索引,即使该索引当前似乎未使用。


@AaronBertrand那么跟踪历史记录(以及最后一次重新启动的时间)是否可以作为此功能的补充?感谢您的回答。
DoubleVu

1
@DoubleVu是的,维护索引使用历史记录的快照可能是值得的,这样您就可以做出受过良好教育的决定,而不受任何可能改变使用情况统计DMV输出的影响。
亚伦·伯特兰

2

是的,自上次重新启动以来,该视图仅具有统计信息。为了缓解这种情况,我设置了一个作业,该作业会运行一个查询,例如您在维护窗口开始每月重新捕获服务器重启之前每月一次在维护窗口之前捕获的查询。这使我可以进一步回顾过去的趋势。我还有第二个查询,它在寻找可能缺少的索引。

要考虑的另一件事是表上还有哪些其他索引。它可能未被使用,因为它大部分或完全是另一个索引的副本。是。SQL Server允许您创建两个不同但相同的索引,因此有可能完全冗余。

您还可以查看如果删除了该索引,使用该索引的查询的查询计划最终可能会变成什么样。它是否将使用另一个索引,或者可能必须回退到全表扫描。

索引最终与艺术一样成为一门艺术,因为实际上很难知道所有可能运行的内容,而且无论如何它最终都会经常变化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.