Bagaimana cara menemukan indeks yang tidak digunakan?

11

Saya sedang mengerjakan gudang data. Saya memiliki tabel dengan catatan hingga 200 juta. Beberapa tabel ini memiliki sekitar 20 indeks (saya tidak bisa memberikan alasan mengapa mereka telah dibuat di tempat pertama). Hal ini membuat pekerjaan mempertahankan indeks ini terlalu menyakitkan dan memiliki dampak langsung pada pekerjaan impor DWH baik dalam kinerja dan jangka waktu.

Bagaimana saya bisa menemukan indeks yang paling jarang digunakan pada setiap tabel? (untuk menyingkirkan mereka)

Muslim Ben Dhaou
sumber
2
Tampilan sistem sys.dm_db_index_usage_statsmenyediakan informasi itu.
Nenad Zivkovic

Jawaban:

10

Coba skrip ini, ini telah membantu saya di masa lalu:

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

Saya telah menemukan bahwa skrip BlitzIndex gratis Brent Ozar Unlimited (ditulis oleh Kendra Little) adalah cara terbaik untuk mengisolasi indeks yang tidak digunakan (serta indeks yang bermanfaat untuk ditambahkan, indeks yang menduplikasi karya indeks lain dll)

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

Ini akan memberi tahu Anda berapa kali indeks apa pun telah dibaca sejak terakhir kali jumlah statistik direset (atau indeks dibuat / diciptakan kembali).

Saya ingat Brent Ozar mengatakan dalam webcast bahwa aturan praktis yang baik adalah tidak lebih dari 10 indeks untuk tabel yang sering dibaca, 20ish untuk tabel yang statis / historis / data yang diarsipkan yang tidak akan sering berubah.

Jika Anda masih mengalami masalah dengan kecepatan impor apakah ada waktu ketika database tidak secara aktif ditanyai (mungkin ini di luar jam kantor). Mungkin bermanfaat untuk menjatuhkan indeks, mengimpor data dan kemudian menerapkan kembali indeks. (Statistik akan diatur ulang tentu saja.) Alasan untuk ini adalah bahwa indeks akan diperbarui ketika setiap catatan masuk, halaman akan disusun ulang dan itu membutuhkan waktu dan disk I / O. Membangun indeks setelah membutuhkan satu pemindaian tabel.

Tidak ada aturan yang keras dan cepat Anda mungkin harus bereksperimen dengan ini tergantung pada jenis indeks dan data yang terlibat. Indeks harus ditinjau secara teratur karena kebutuhan / permintaan berubah.

Greg Robson
sumber
1
Saya sudah menjalankan skrip ini tetapi berharap ada panduan sederhana untuk menafsirkannya.
IrishChieftain
0

Coba ini:

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

Saya telah menambahkan tanggal dan kode yang terakhir digunakan untuk menjatuhkan ke permintaan 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
mike nelson
sumber