จะหาดัชนีที่ไม่ได้ใช้อย่างไร


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

ฉันพบว่าสคริปต์ BlitzIndex ฟรีของ Brent Ozar Unlimited (เขียนโดย Kendra Little) เป็นวิธีที่ดีที่สุดในการแยกดัชนีที่ไม่ได้ใช้ (รวมถึงดัชนีที่เป็นประโยชน์ต่อการเพิ่มดัชนีที่ทำซ้ำงานของดัชนีอื่น ๆ เป็นต้น)

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

มันจะบอกคุณถึงจำนวนครั้งที่มีการอ่านดัชนีตั้งแต่ครั้งล่าสุดที่มีการรีเซ็ตจำนวนสถิติ (หรือดัชนีถูกสร้าง / สร้างใหม่)

ฉันดูเหมือนจะจำได้ว่า Brent Ozar พูดในเว็บคาสต์ว่ากฎง่ายดีไม่เกิน 10 ดัชนีสำหรับตารางที่อ่านบ่อย 20ish สำหรับตารางที่ข้อมูลคงที่ / ประวัติ / เก็บถาวรที่จะไม่เปลี่ยนแปลงบ่อย

หากคุณยังคงมีปัญหาเกี่ยวกับความเร็วในการนำเข้าจะมีเวลาที่ฐานข้อมูลไม่ได้ถูกสอบถามอย่างแข็งขัน (บางทีนี่อาจเป็นนอกเวลาทำการ) มันอาจจะเป็นประโยชน์ในการวางดัชนีนำเข้าข้อมูลแล้วนำดัชนีไปใช้อีกครั้ง (สถิติจะถูกรีเซ็ตแน่นอน) เหตุผลสำหรับสิ่งนี้คือดัชนี (es) จะได้รับการอัปเดตเมื่อแต่ละระเบียนเข้าสู่หน้าต่างๆจะได้รับการจัดเรียงใหม่และต้องใช้เวลาและดิสก์ 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.