Wie finde ich nicht verwendete Indizes?

11

Ich arbeite an einem Data Warehouse. Ich habe Tabellen mit bis zu 200 Millionen Datensätzen. Einige dieser Tabellen haben mehr als 20 Indizes (ich kann keinen Grund angeben, warum sie überhaupt erstellt wurden). Dies macht die Verwaltung dieser Indizes zu schmerzhaft und wirkt sich sowohl in Bezug auf die Leistung als auch auf die Laufzeit direkt auf den DWH-Importjob aus.

Wie finde ich die am wenigsten verwendeten Indizes für jede Tabelle? (um sie loszuwerden)

Moslem Ben Dhaou
quelle
2
Die Systemansicht sys.dm_db_index_usage_statsbietet diese Informationen.
Nenad Zivkovic

Antworten:

10

Probieren Sie dieses Skript aus. Es hat mir in der Vergangenheit geholfen:

-- 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

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

Paul White 9
quelle
10

Ich habe festgestellt, dass das kostenlose BlitzIndex-Skript von Brent Ozar Unlimited (geschrieben von Kendra Little) der beste Weg ist, nicht verwendete Indizes zu isolieren (sowie Indizes, deren Hinzufügen von Vorteil ist, Indizes, die die Arbeit anderer Indizes duplizieren usw.).

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

Hier erfahren Sie, wie oft ein Index seit dem letzten Zurücksetzen der Statistikanzahl gelesen wurde (oder ein Index erstellt / neu erstellt wurde).

Ich erinnere mich an Brent Ozar, der im Webcast sagte, dass eine gute Faustregel nicht mehr als 10 Indizes für eine häufig gelesene Tabelle ist, 20ish für Tabellen mit statischen / historischen / archivierten Daten, die sich nicht häufig ändern.

Wenn Sie immer noch Probleme mit der Importgeschwindigkeit haben, wird die Datenbank möglicherweise nicht aktiv abgefragt (möglicherweise außerhalb der Bürozeiten). Es kann vorteilhaft sein, den Index zu löschen, die Daten zu importieren und die Indizes erneut anzuwenden. (Die Statistiken werden natürlich zurückgesetzt.) Der Grund dafür ist, dass die Indizes bei jedem Datensatz aktualisiert werden, die Seiten neu angeordnet werden und dies Zeit und Festplatten-E / A erfordert. Das Erstellen der Indizes nach erfordert einen einzelnen Scan der Tabelle.

Abhängig von den Indextypen und den beteiligten Daten müssen Sie möglicherweise nicht mit dieser Regel experimentieren. Indizes sollten regelmäßig überprüft werden, wenn sich Anforderungen / Abfragen ändern.

Greg Robson
quelle
1
Ich habe dieses Skript ausgeführt, wünschte jedoch, es gäbe eine einfache Anleitung zur Interpretation.
IrishChieftain
0

Versuche dies:

SELECT   OBJECT_NAME(S.[OBJECT_ID]) AS [OBJECT NAME], 
             I.[NAME] AS [INDEX NAME], 
             USER_SEEKS, 
             USER_SCANS, 
             USER_LOOKUPS, 
             USER_UPDATES 
    FROM     SYS.DM_DB_INDEX_USAGE_STATS AS S 
             INNER JOIN SYS.INDEXES AS I 
               ON I.[OBJECT_ID] = S.[OBJECT_ID] 
                  AND I.INDEX_ID = S.INDEX_ID 
    WHERE    OBJECTPROPERTY(S.[OBJECT_ID],'IsUserTable') = 1 

Raj

Raj
quelle
0

Ich habe das zuletzt verwendete Datum und den Code zum Löschen in Rajs Abfrage hinzugefügt.

SELECT   OBJECT_NAME(S.[OBJECT_ID]) AS [OBJECT NAME], 
             I.[NAME] AS [INDEX NAME], type_desc,
             coalesce(last_user_seek,last_user_scan,last_user_lookup,last_system_scan,last_system_seek,last_system_lookup) as LastUsed,
             USER_SEEKS, 
             USER_SCANS, 
             USER_LOOKUPS, 
             USER_UPDATES ,
             last_user_seek,last_user_scan,last_user_lookup,last_system_scan,last_system_seek,last_system_lookup,
             'drop index ['+I.[NAME]+'] on ['+OBJECT_NAME(S.[OBJECT_ID])+'];' as DropStatement
    FROM     SYS.DM_DB_INDEX_USAGE_STATS AS S 
             INNER JOIN SYS.INDEXES AS I 
               ON I.[OBJECT_ID] = S.[OBJECT_ID] 
                  AND I.INDEX_ID = S.INDEX_ID 
    WHERE    OBJECTPROPERTY(S.[OBJECT_ID],'IsUserTable') = 1 
    order by type_desc,coalesce(last_user_seek,last_user_scan,last_user_lookup,last_system_scan,last_system_seek,last_system_lookup) desc
mike nelson
quelle