dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Scripts Library/sqlserver/#50
Script #50
sqlserver
Performanceread-onlyMin Version: 2012

Find Unused and Costly Indexes in SQL Server

Finds indexes that are updated but never read. Produces a drop-candidate list to reduce write cost.

#unused-index#index-usage#dmv
sqlserver · sql
SELECT OBJECT_SCHEMA_NAME(i.object_id) AS schema_name,
       OBJECT_NAME(i.object_id) AS table_name,
       i.name AS index_name, i.type_desc,
       ISNULL(s.user_seeks,0) + ISNULL(s.user_scans,0) + ISNULL(s.user_lookups,0) AS reads,
       ISNULL(s.user_updates,0) AS writes,
       (SELECT SUM(ps.used_page_count) * 8 / 1024 FROM sys.dm_db_partition_stats ps
         WHERE ps.object_id = i.object_id AND ps.index_id = i.index_id) AS size_mb
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats s
       ON s.object_id = i.object_id AND s.index_id = i.index_id AND s.database_id = DB_ID()
WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1
  AND i.type_desc = 'NONCLUSTERED'
  AND i.is_primary_key = 0 AND i.is_unique_constraint = 0
  AND ISNULL(s.user_seeks,0) + ISNULL(s.user_scans,0) + ISNULL(s.user_lookups,0) = 0
ORDER BY writes DESC;
Operational Notes & Remediation Guidance

Indexes with high `user_updates` and zero `user_seeks`/`user_scans` incur heavy write penalties without providing read benefit.

Production Safety & Execution Standards
  • This script is designed for read-only diagnostics; it does not alter schema or modify data directly.
  • Prior to executing on production systems under high load, verify the target database version (Min. Version: 2012).
  • Exercise caution with mutating actions (e.g., terminating sessions or dropping indexes) referenced in the notes section.