사용하지 않는 인덱스를 찾는 방법은 무엇입니까?


11

데이터웨어 하우스에서 작업하고 있습니다. 최대 200M 레코드가있는 테이블이 있습니다. 이 테이블 중 일부에는 약 20 개 이상의 색인이 있습니다 (처음에 테이블이 작성된 이유는 제공 할 수 없습니다). 이로 인해 이러한 인덱스를 유지 관리하는 작업이 너무 어려워지고 성능과 런타임 모두에서 DWH 가져 오기 작업에 직접적인 영향을 미칩니다.

각 테이블에서 가장 적게 사용 된 인덱스를 어떻게 찾을 수 있습니까? (그들을 없애기 위해)


2
시스템보기 sys.dm_db_index_usage_stats는 해당 정보를 제공합니다.
Nenad Zivkovic

답변:


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

나는 Brent Ozar Unlimited의 무료 BlitzIndex 스크립트 (Kendra Little이 작성)가 사용되지 않은 인덱스 (추가하기에 유리한 인덱스, 다른 인덱스의 작업을 복제하는 인덱스 등)를 분리하는 가장 좋은 방법이라는 것을 알았습니다.

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

통계 계수가 마지막으로 재설정 된 이후 (또는 인덱스가 작성 / 재 작성된) 이후에 인덱스를 읽은 횟수를 알려줍니다.

브렌트 오자 (Brent Ozar)는 웹 캐스트에서 좋은 경험 법칙은 자주 읽히는 테이블의 인덱스가 10 개를 넘지 않으며, 자주 변경되지 않는 정적 / 역사적 / 아카이브 데이터 인 테이블의 경우 20 일을 넘지 않는다고 말합니다.

가져 오기 속도에 여전히 문제가있는 경우 데이터베이스가 활발하게 쿼리되지 않는 시간이 있습니다 (아마도 근무 시간이 아님). 인덱스를 삭제하고 데이터를 가져온 다음 인덱스를 다시 적용하는 것이 좋습니다. (통계는 물론 재설정됩니다.) 그 이유는 각 레코드가 들어올 때 색인이 업데이트되고 페이지가 다시 정렬되며 시간과 디스크 I / O가 걸리기 때문입니다. 이후 에 인덱스를 빌드 하려면 테이블을 한 번 스캔해야합니다.

색인 유형 및 관련 데이터에 따라이를 실험해야 할 수도 있습니다. 필요 / 조회가 변경되면 색인을 정기적으로 검토해야합니다.


1
이 스크립트를 실행했지만이를 해석하기위한 간단한 가이드가 있었으면 좋겠다.
IrishChieftain

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

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.