Як знайти невикористані індекси?


11

Я працюю на сховищі даних. У мене є таблиці з записом до 200 млн. Деякі з цих таблиць мають близько 20+ індексів (я не можу навести причину, чому вони були створені в першу чергу). Це робить завдання з підтримки цих індексів занадто болісним і має прямий вплив на роботу імпорту DWH як на продуктивність, так і на час виконання.

Як я можу знайти найменш використані індекси у кожній таблиці? (щоб позбутися від них)


2
Система подання sys.dm_db_index_usage_statsнадає цю інформацію.
Ненад Живкович

Відповіді:


10

Спробуйте цей сценарій, Він допоміг мені в минулому:

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

Я виявив, що безкоштовний сценарій BlitzIndex Brent Ozar Unlimited (написаний Кендра Літл) - найкращий спосіб виділити невикористані індекси (а також індекси, які вигідно додавати, індекси, що дублюють роботу інших індексів тощо)

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

Він повідомить вам, скільки разів було прочитано будь-який індекс з моменту останнього скидання статистичних підрахунків (або створено / відтворито індекс).

Мені здається, я пам’ятаю, що Брент Озар говорив у веб-трансляції, що гарне правило - це не більше 10 індексів для таблиці, яка читається часто, 20 балів для таблиць, які є статичними / історичними / заархівованими даними, які не змінюватимуться часто.

Якщо у вас все ще виникають проблеми зі швидкістю імпорту, є час, коли база даних не запитується активно (можливо, це поза робочим часом). Може бути корисним скинути індекс, імпортувати дані, а потім повторно застосувати індекси. (Статистика буде скинуто, звичайно.) Причиною цього є те, що індекси (и) оновлюватимуться по мірі надходження кожного запису, сторінки будуть упорядковані, і це потребує часу та дискового вводу / виводу. Побудова індексів після вимагає одного сканування таблиці.

Немає жорсткого і швидкого правила, можливо, вам не доведеться експериментувати з цим залежно від типів індексу та даних, що беруться. Індекси слід регулярно переглядати при зміні потреб / запитів.


1
Я керував цим сценарієм, але хотілося, щоб було просте керівництво для його тлумачення.
Ірландський шеф

0

Спробуйте це:

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 

Радж


0

Я додав останню використану дату та код для переходу до запиту Радж.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.