Come trovare indici inutilizzati?


11

Sto lavorando a un data warehouse. Ho tabelle con un massimo di 200 milioni di record. Alcune di queste tabelle hanno circa 20+ indici (non posso fornire un motivo per cui sono state create in primo luogo). Ciò sta rendendo il lavoro di mantenimento di questi indici troppo doloroso e ha un impatto diretto sul lavoro di importazione DWH sia in termini di prestazioni che di runtime.

Come posso trovare gli indici meno utilizzati su ogni tabella? (per sbarazzarsi di loro)


2
La vista Sistema sys.dm_db_index_usage_statsfornisce tali informazioni.
Nenad Zivkovic,

Risposte:


10

Prova questo script, mi ha aiutato in passato:

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


10

Ho scoperto che lo script BlitzIndex gratuito di Brent Ozar Unlimited (scritto da Kendra Little) è il modo migliore per isolare gli indici inutilizzati (così come gli indici che sono utili da aggiungere, gli indici che duplicano il lavoro di altri indici ecc.)

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

Indica il numero di volte in cui un indice è stato letto dall'ultima reimpostazione dei conteggi delle statistiche (o è stato creato / ricreato un indice).

Mi sembra di ricordare che Brent Ozar abbia detto nel webcast che una buona regola empirica non è più di 10 indici per una tabella che viene letta spesso, 20ish per le tabelle che sono dati statici / storici / archiviati che non cambieranno frequentemente.

Se continui ad avere problemi con la velocità di importazione c'è un momento in cui il database non viene interrogato attivamente (forse questo è fuori orario di ufficio). Potrebbe essere utile eliminare l'indice, importare i dati e quindi riapplicare gli indici. (Le statistiche verranno ripristinate, ovviamente.) La ragione di ciò è che gli indici verranno aggiornati man mano che ogni record entra, le pagine verranno riordinate e ciò richiederà tempo e I / O del disco. La creazione degli indici dopo richiede una singola scansione della tabella.

Nessuna regola rigida e veloce potrebbe essere necessario sperimentare questo a seconda dei tipi di indice e dei dati coinvolti. Gli indici dovrebbero essere periodicamente rivisti al variare delle esigenze / richieste.


1
Ho eseguito questo script ma vorrei che ci fosse una semplice guida per interpretarlo.
IrishChieftain

0

Prova questo:

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


0

Ho aggiunto la data e il codice dell'ultimo utilizzo per passare alla query di Raj.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.