如何找到未使用的索引?

Mos*_*aou 10 sql-server ssms

我正在研究数据仓库。我有多达 200M 记录的表。其中一些表有大约 20 多个索引(我无法提供最初创建它们的原因)。这使得维护这些索引的工作变得过于痛苦,并且在性能和运行时都会直接影响 DWH 导入工作。

如何在每个表上找到最少使用的索引?(为了摆脱它们)

小智 10

试试这个脚本,它在过去帮助过我:

-- Unused Index Script
-- Original Author: Pinal Dave 
SELECT TOP 25
o.name AS ObjectName
, i.name AS IndexName
, i.index_id AS IndexID
, dm_ius.user_seeks AS UserSeek
, dm_ius.user_scans AS UserScans
, dm_ius.user_lookups AS UserLookups
, dm_ius.user_updates AS UserUpdates
, p.TableRows
, 'DROP INDEX ' + QUOTENAME(i.name)
+ ' ON ' + QUOTENAME(s.name) + '.'
+ QUOTENAME(OBJECT_NAME(dm_ius.OBJECT_ID)) AS 'drop statement'
FROM sys.dm_db_index_usage_stats dm_ius
INNER JOIN sys.indexes i ON i.index_id = dm_ius.index_id 
AND dm_ius.OBJECT_ID = i.OBJECT_ID
INNER JOIN sys.objects o ON dm_ius.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN (SELECT SUM(p.rows) TableRows, p.index_id, p.OBJECT_ID
FROM sys.partitions p GROUP BY p.index_id, p.OBJECT_ID) p
ON p.index_id = dm_ius.index_id AND dm_ius.OBJECT_ID = p.OBJECT_ID
WHERE OBJECTPROPERTY(dm_ius.OBJECT_ID,'IsUserTable') = 1
AND dm_ius.database_id = DB_ID()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
ORDER BY (dm_ius.user_seeks + dm_ius.user_scans + dm_ius.user_lookups) ASC
Run Code Online (Sandbox Code Playgroud)

http://blog.sqlauthority.com/2011/01/04/sql-server-2008-unused-index-script-download/


小智 10

我发现 Brent Ozar Unlimited 的免费BlitzIndex 脚本(由 Kendra Little 编写)是隔离未使用索引(以及有利于添加的索引、复制其他索引工作的索引等)的最佳方法

http://www.brentozar.com/blitzindex/

它会告诉您自上次重置统计计数(或创建/重新创建索引)以来读取任何索引的次数。

我似乎记得 Brent Ozar 在网络广播中说过,一个好的经验法则是,对于经常读取的表,索引不超过 10 个,对于不会经常更改的静态/历史/存档数据的表,索引不超过 20 个。

如果您仍然遇到导入速度问题,是否有一段时间未主动查询数据库(可能是非办公时间)。删除索引、导入数据然后重新应用索引可能会有所帮助。(当然,统计数据会被重置。)这样做的原因是索引将随着每条记录的进入而更新,页面将被重新排序,这需要时间和磁盘 I/O。建立索引,需要该表的单次扫描。

没有硬性规定,您可能必须根据索引类型和所涉及的数据进行试验。随着需求/查询的变化,应定期审查索引。