SQL Server: Ungenutzte Indizes finden und Datenbanken optimieren

Ungenutzte Indizes sind stiller Performance-Killer: Sie verlangsamen INSERT/UPDATE/DELETE-Operationen, verbrauchen Speicherplatz und erhöhen die I/O-Last – ohne dem Leser irgendeinen Nutzen zu bringen. Diese Queries helfen, sie zu identifizieren.

Ungenutzte Indizes seit Server-Start

SELECT
    OBJECT_NAME(i.object_id) AS table_name,
    i.name AS index_name,
    i.type_desc,
    ius.user_seeks,
    ius.user_scans,
    ius.user_lookups,
    ius.user_updates,
    ius.last_user_seek,
    ius.last_user_scan
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats ius
    ON i.object_id = ius.object_id
    AND i.index_id = ius.index_id
    AND ius.database_id = DB_ID()
WHERE i.type > 0  -- Kein Heap
  AND OBJECT_NAME(i.object_id) NOT LIKE 'sys%'
  AND (ius.user_seeks IS NULL
       OR (ius.user_seeks = 0 AND ius.user_scans = 0 AND ius.user_lookups = 0))
ORDER BY ius.user_updates DESC NULLS LAST;

Speicherplatz ungenutzter Indizes

-- Wie viel Speicher beanspruchen ungenutzte Indizes?
SELECT
    OBJECT_NAME(i.object_id) AS table_name,
    i.name AS index_name,
    SUM(a.total_pages) * 8 / 1024.0 AS size_mb
FROM sys.indexes i
JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE i.is_primary_key = 0
  AND i.is_unique = 0
GROUP BY i.object_id, i.name
HAVING SUM(a.total_pages) * 8 / 1024.0 > 10  -- Nur Indizes > 10MB
ORDER BY size_mb DESC;

Wichtig: Indizes sollten nur nach einem vollständigen Repräsentativ-Workload-Zeitraum (mindestens 1-2 Wochen) als “ungenutzt” eingestuft werden. Nach einem Server-Neustart werden alle Index-Statistiken zurückgesetzt.