DECLARE @dbid INT
--To get Datbase ID
SET @dbid = Db_id( )
--This query will order result according to index usage, which can help you to find which indexes are highly used and requires more attention
-- I am not using index upadate count over here since we requires details of index usage for search operations
-- Join this view to Sys.indexes to get name of indexes. Index name will be null where there is no index exist and table scan happens.
--Here index_name and index_column may come NULL, where no index exists and SQL Server refers table directly which is called heap.
SELECT
Db_name( d.database_id ) database_name
,Object_name( d.object_id ) object_name
,s.name index_name
,c.index_columns
,d.*
FROM
sys.dm_db_index_usage_stats d
INNER JOIN sys.indexes s
ON d.object_id=s.object_id
AND d.index_id=s.index_id
LEFT OUTER JOIN ( SELECT DISTINCT
object_id
,index_id
,Stuff( ( SELECT
','+Col_name( object_id, column_id ) AS 'data()'
FROM
sys.index_columns t2
WHERE t1.object_id=t2.object_id
AND t1.index_id=t2.index_id
FOR XML PATH ('') ), 1, 1, '' ) AS 'index_columns'
FROM
sys.index_columns t1 ) c
ON c.index_id=s.index_id
AND c.object_id=s.object_id
WHERE database_id=@dbid
AND Objectproperty( d.object_id, 'IsIndexable' )=1
ORDER BY
index_columns
,object_name
,( user_seeks+user_scans+user_lookups+system_seeks+system_scans+system_lookups ) DESC
-- To find index scans
SELECT
Db_name( d.database_id ) database_name
,Object_name( d.object_id ) object_name
,s.name index_name
,c.index_columns
,d.*
FROM
sys.dm_db_index_usage_stats d
INNER JOIN sys.indexes s
ON d.object_id=s.object_id
AND d.index_id=s.index_id
LEFT OUTER JOIN ( SELECT DISTINCT
object_id
,index_id
,Stuff( ( SELECT
','+Col_name( object_id, column_id ) AS 'data()'
FROM
sys.index_columns t2
WHERE t1.object_id=t2.object_id
AND t1.index_id=t2.index_id
FOR XML PATH ('') ), 1, 1, '' ) AS 'index_columns'
FROM
sys.index_columns t1 ) c
ON c.index_id=s.index_id
AND c.object_id=s.object_id
WHERE database_id=@dbid
AND Objectproperty( d.object_id, 'IsIndexable' )=1
AND ( d.user_scans+d.system_scans )>0
ORDER BY
d.user_scans+d.system_scans
--To find unused indexes
-- This query will give you details of unused indexes with details like object_name index_name,index_type , index columns .
-- We are considering only indexes so we are omitting index_type heap, clustered since it represents tables
SELECT
Object_name( i.object_id ) object_name
,i.name index_name
,i.index_id index_id
,i.type_desc type_desc
,c.index_columns
FROM
sys.indexes i
LEFT OUTER JOIN sys.dm_db_index_usage_stats d
ON d.object_id=i.object_id
AND i.index_id=d.index_id
AND d.database_id=@dbid
LEFT OUTER JOIN ( SELECT DISTINCT
object_id
,index_id
,Stuff( ( SELECT
','+Col_name( object_id, column_id ) AS 'data()'
FROM
sys.index_columns t2
WHERE t1.object_id=t2.object_id
AND t1.index_id=t2.index_id
FOR XML PATH ('') ), 1, 1, '' ) AS 'index_columns'
FROM
sys.index_columns t1 ) c
ON c.index_id=i.index_id
AND c.object_id=i.object_id
WHERE Objectproperty( i.object_id, 'IsIndexable' )=1
AND d.index_id IS NULL
AND i.type_desc NOT IN ( 'heap', 'clustered' )
-- To find only indexes which are only updated but not used in index seek, lookup or scan.
SELECT
Object_name( i.object_id ) object_name
,i.name index_name
,i.index_id index_id
,i.type_desc type_desc
,c.index_columns
,d.user_updates
,d.user_seeks
,d.user_scans
,d.user_lookups
,d.system_updates
,d.system_seeks
,d.system_scans
,d.system_lookups
FROM
sys.indexes i
INNER JOIN sys.dm_db_index_usage_stats d
ON d.object_id=i.object_id
AND i.index_id=d.index_id
AND d.database_id=@dbid
LEFT OUTER JOIN ( SELECT DISTINCT
object_id
,index_id
,Stuff( ( SELECT
','+Col_name( object_id, column_id ) AS 'data()'
FROM
sys.index_columns t2
WHERE t1.object_id=t2.object_id
AND t1.index_id=t2.index_id
FOR XML PATH ('') ), 1, 1, '' ) AS 'index_columns'
FROM
sys.index_columns t1 ) c
ON c.index_id=i.index_id
AND c.object_id=i.object_id
WHERE Objectproperty( i.object_id, 'IsIndexable' )=1
AND i.type_desc NOT IN ( 'heap', 'clustered' )
AND ( d.user_updates>0
OR d.system_updates>0 )
AND d.user_seeks=0
AND d.user_scans=0
AND d.user_lookups=0
AND d.system_seeks=0
AND d.system_scans=0
AND d.system_lookups=0
Regards
Amish Shah
August 7, 2008 at 6:25 am |
cool stuffEdwin
September 3, 2008 at 7:09 am |
Really helpfull
April 27, 2009 at 8:04 pm |
Hi, I found your scripts about index usages very useful. Good work
June 26, 2009 at 5:29 pm |
Very useful script. Thanks budby.
June 14, 2012 at 4:56 pm |
Great stuff – thank you for posting this!