Performance 04: unused indexes

Run it in the database: indexes that are written to but never read since start-up. Only meaningful once the server has been up through a full business cycle (month end and so on). Read-only, changes nothing. Tested on SQL Server 2017 and 2025.

-- 04_Unused_Indexes.sql - run IN the database: indexes that are written to but never read since start-up. Read-only.
-- Only meaningful after the server has been up through a full business cycle (month end etc.).
SET NOCOUNT ON;
SELECT OBJECT_SCHEMA_NAME(i.object_id) + N'.' + OBJECT_NAME(i.object_id) AS [table], i.name AS [index], i.type_desc,
       ISNULL(us.user_seeks + us.user_scans + us.user_lookups, 0) AS reads, ISNULL(us.user_updates, 0) AS writes,
       (SELECT SUM(ps.used_page_count) / 128 FROM sys.dm_db_partition_stats AS ps WHERE ps.object_id = i.object_id AND ps.index_id = i.index_id) AS size_mb,
       (SELECT sqlserver_start_time FROM sys.dm_os_sys_info) AS counting_since
FROM sys.indexes AS i
LEFT JOIN sys.dm_db_index_usage_stats AS us ON us.object_id = i.object_id AND us.index_id = i.index_id AND us.database_id = DB_ID()
WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1 AND i.type_desc = N'NONCLUSTERED'
  AND i.is_primary_key = 0 AND i.is_unique_constraint = 0
  AND ISNULL(us.user_seeks + us.user_scans + us.user_lookups, 0) = 0
ORDER BY writes DESC;