To interesujące pytanie. W ciągu ostatniego tygodnia pracowałem nad tym samym pytaniem. Istnieje tabela systemowa o nazwie dm_db_index_usage_stats, która zawiera statystyki użycia indeksów.
indeksy, które nie pojawiają się w statystykach wykorzystania tabeli
Jednak wiele indeksy nigdy nie pojawiają się w tej tabeli w ogóle. Zapytanie, które napisał David Andres, zawiera listę wszystkich indeksów dla tego przypadku. Zaktualizowałem go nieco, aby zignorować klucze podstawowe, które prawdopodobnie nie powinny zostać usunięte, nawet jeśli nie są nigdy używane. Dołączyłem również do tabeli dm_db_index_physical_stats, aby uzyskać inne informacje, w tym liczbę stron, całkowity rozmiar indeksu i procent fragmentacji. Interesujące jest to, że indeksy zwracane przez to zapytanie nie pojawiają się w raporcie SQL dla statystyk użycia indeksu.
DECLARE @dbid INT
SELECT @dbid = DB_ID(DB_NAME())
SELECT Databases.Name AS [Database],
Objects.NAME AS [Table],
Indexes.NAME AS [Index],
Indexes.INDEX_ID,
PhysicalStats.page_count as [Page Count],
CONVERT(decimal(18,2), PhysicalStats.page_count * 8/1024.0) AS [Total Index Size (MB)],
CONVERT(decimal(18,2), PhysicalStats.avg_fragmentation_in_percent) AS [Fragmentation (%)]
FROM SYS.INDEXES Indexes
INNER JOIN SYS.OBJECTS Objects ON Indexes.OBJECT_ID = Objects.OBJECT_ID
LEFT JOIN sys.dm_db_index_physical_stats(@dbid, null, null, null, null) PhysicalStats
on PhysicalStats.object_id = Indexes.object_id and PhysicalStats.index_id = indexes.index_id
INNER JOIN sys.databases Databases
ON Databases.database_id = PhysicalStats.database_id
WHERE OBJECTPROPERTY(Objects.OBJECT_ID,'IsUserTable') = 1
AND Indexes.type = 2 -- Nonclustered indexes
AND Indexes.INDEX_ID NOT IN (
SELECT UsageStats.INDEX_ID
FROM SYS.DM_DB_INDEX_USAGE_STATS UsageStats
WHERE UsageStats.OBJECT_ID = Indexes.OBJECT_ID
AND Indexes.INDEX_ID = UsageStats.INDEX_ID
AND DATABASE_ID = @dbid)
ORDER BY PhysicalStats.page_count DESC,
Objects.NAME,
Indexes.INDEX_ID,
Indexes.NAME ASC
indeksy, które są widoczne w statystykach wykorzystania tabeli, ale nigdy nie zostaną Używane
Istnieją inne wskaźniki, które pojawiają się na stole dm_db_index_usage_stats, które jednak nigdy nie zostały wykorzystane do użytkownik chce, skany lub wyszukiwania. To zapytanie zidentyfikuje indeksy należące do tej kategorii. Nawiasem mówiąc, w przeciwieństwie do indeksów zwróconych z innego zapytania, indeksy zwrócone w tym zapytaniu mogą być zweryfikowane w raporcie SQL według statystyk użycia indeksu.
Dodałem minimalną liczbę stron, która pozwala mi początkowo skupić się na i usunąć nieużywane indeksy, które zajmują dużo miejsca.
DECLARE @MinimumPageCount int
SET @MinimumPageCount = 500
SELECT Databases.name AS [Database],
Indexes.name AS [Index],
Objects.Name AS [Table],
PhysicalStats.page_count as [Page Count],
CONVERT(decimal(18,2), PhysicalStats.page_count * 8/1024.0) AS [Total Index Size (MB)],
CONVERT(decimal(18,2), PhysicalStats.avg_fragmentation_in_percent) AS [Fragmentation (%)],
ParititionStats.row_count AS [Row Count],
CONVERT(decimal(18,2), (PhysicalStats.page_count * 8.0 * 1024)/ParititionStats.row_count) AS [Index Size/Row (Bytes)]
FROM sys.dm_db_index_usage_stats UsageStats
INNER JOIN sys.indexes Indexes
ON Indexes.index_id = UsageStats.index_id
AND Indexes.object_id = UsageStats.object_id
INNER JOIN sys.objects Objects
ON Objects.object_id = UsageStats.object_id
INNER JOIN SYS.databases Databases
ON Databases.database_id = UsageStats.database_id
INNER JOIN sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS PhysicalStats
ON PhysicalStats.index_id = UsageStats.Index_id
and PhysicalStats.object_id = UsageStats.object_id
INNER JOIN SYS.dm_db_partition_stats ParititionStats
ON ParititionStats.index_id = UsageStats.index_id
and ParititionStats.object_id = UsageStats.object_id
WHERE UsageStats.user_scans = 0
AND UsageStats.user_seeks = 0
AND UsageStats.user_lookups = 0
AND PhysicalStats.page_count > @MinimumPageCount -- ignore indexes with less than 500 pages of memory
AND Indexes.type_desc != 'CLUSTERED' -- Exclude primary keys, which should not be removed
ORDER BY [Page Count] DESC
Mam nadzieję, że to pomoże.
ostatnia myśl
Oczywiście, gdy indeksy są identyfikowane jako kandydatów do usuwania, rozwagą powinny być nadal stosowane, aby upewnić się, że to dobra decyzja, aby to zrobić.
Aby uzyskać więcej informacji, zobacz Identifying Unused Indexes in a SQL Server Database