views:

214

answers:

4

I am trying to determine what indexes are no longer used in my Database. I have had great luck using the following query:

SELECT   OBJECT_NAME(S.[OBJECT_ID]) AS [OBJECT NAME],
         I.[NAME] AS [INDEX NAME],
         i.Type_Desc as [Index Type],
         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 i.name is not null
AND 
    (   OBJECT_NAME(S.[OBJECT_ID]) = 'Table1'
        OR
        OBJECT_NAME(S.[OBJECT_ID]) = 'Table2'
        OR
        OBJECT_NAME(S.[OBJECT_ID]) = 'Table3'
    )
ORder by S.[OBJECT_ID], user_Seeks desc , user_scans desc

What I would like to find now is what Stored Procedures are causing the Seekds, scans and lookups that The above query reports on. Is this information stored in the system views/tables?

CLARIFICATION

As gbn has pointed out a Stored Procedure does not directly use an index, it uses a table that uses an index. Below is an explanation that I hope will clarify what I am trying to ask here.

Is it possible for me to determine what SQL was run that caused the above indexes to be used? For example if one of the indexes reported on has 10 User_Seeks would it be possible to determine that exec sp_1 caused that usage 7 times and exec sp_2 caused that usage 3 times?

A: 

In the SQL management studio, you can see exactly how the query is executed by using the "Display Execution Plan" option under the Query menu.

Jesse Weigert
I'm aware of that but if I have 100 stored procedures i'd rather not go through each one and find this information manually. What I'm trying to find out is if there is a system table or view that I can query to find out what indexes are used by what procs
Abe Miessler
+2  A: 

Edit (again, after question update):

No realistic chance. You could try profiler and capture the textplan. I saw this once and it killed a server though: it's a lot of text to record. YMMV :-)

Stored procedures do not use indexes.

Stored procs use tables (and indexed views) that then use indexes (or don't use as you've worked out above)

Doing SELECT col1, col2 FROM myTable WHERE col2 = 'foo' ORDER BY col1 is the same whether it's in a stored procedure, view, user defined fucntion or by itself.

Edit: Our index usage script, downloaded from somewhere...

SELECT
    o.name AS [object_name], 
    i.name AS index_name, 
    i.type_desc, 
    u.user_seeks, u.user_scans, 
    u.user_lookups, u.user_updates,
    o.type
FROM
    sys.indexes i
    JOIN
    sys.objects o ON i.[object_id] = o.[object_id]
    LEFT JOIN 
    sys.dm_db_index_usage_stats u ON i.[object_id] = u.[object_id] AND 
                                    i.index_id = u.index_id AND 
                                    u.database_id = DB_ID()
WHERE
    o.type IN ('U', 'V') AND
    i.name IS NOT NULL
ORDER BY 
    u.user_seeks + u.user_scans + u.user_lookups, u.user_updates
gbn
Well you've got me there gbn. Would you like me to rephrase my question or do you understand the spirit of what i'm trying to say?
Abe Miessler
You'll have to rephrase... because stored procs still won't use indexes...
gbn
Abe, this might seem pedantic, but there are good reasons for being clear in communication about technical subjects like this one. One reason being 'do you want the right answer?'
DaveE
Heh, thanks for the reminder Dave. I've updated my question with a clarification section. Please let me know if it is still confusing.
Abe Miessler
Thanks for the help gbn, i'll be sure to phrase my index usage questions properly in the future :)
Abe Miessler
A: 

I don't have access to SQL Management Studio at home, but maybe you can look at the stored procdures dependancies (i.e. this store procedure depends on these tables and therefore may use these indexes)

This page might give you some clue, like using the INFORMATION_SCHEMA.ROUTINES system table:

SELECT routine_name, routine_type 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%Employee%'

You can populate this information into a temp table and then then use that to query for the indexes used, looking at the index usage stats.

Sorry that I'm not able to give you a practical example, just a theorical example...

Guy
never use INFORMATION_SCHEMA.ROUTINES. Always use sys.sql_modules. ROUTINE_DEFINITION is nvarchar(4000): you can work out why this breaks...
gbn
+1  A: 

You have the number of executions for all statements in sys.dm_exec_query_stats, and you can extract the plan XML using sys.dm_exec_query_plan. The plan contains details like scan operators used, so between these two you can make up a lot of information from what you ask. For example the following query will show you the IndexScan operators in the frequently run statements from the cached plans that are causing many logical reads:

with xmlnamespaces ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sp)
select top(100) 
  q.total_logical_reads, q.execution_count
  , x.value(N'@Database', N'sysname') as [Database]
  , x.value(N'@Schema', N'sysname') as [Schema]
  , x.value(N'@Table', N'sysname') as [Table]
  , x.value(N'@Index', N'sysname') as [Index]
  , substring(t.text, q.statement_start_offset/2,   
  case when 0 < q.statement_end_offset then (q.statement_end_offset - q.statement_start_offset)/2
  else len(t.text) - q.statement_start_offset/2 end) as [Statement]
from sys.dm_exec_query_stats q
cross apply sys.dm_exec_query_plan(plan_handle)
cross apply sys.dm_exec_sql_text(sql_handle) as t
cross apply query_plan.nodes(N'//sp:IndexScan/sp:Object') s(x)
where execution_count > 100
order by total_logical_reads desc;
Remus Rusanu