2010-02-11 14 views
8

Estoy tratando de determinar qué índices ya no se usan en mi base de datos. He tenido una gran suerte utilizando la siguiente consulta:¿Cómo encontrar qué procedimientos almacenados usan qué índices?

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 

Lo que me gustaría encontrar ahora es qué procedimientos almacenados están causando la busca, exploraciones y búsquedas que dan La consulta anterior informa sobre. ¿Esta información está almacenada en las vistas/tablas del sistema?

CLARIFICACION

Como GBN ha señalado un procedimiento almacenado no utiliza directamente un índice, se utiliza una tabla que utiliza un índice. A continuación hay una explicación que espero aclarará lo que estoy tratando de preguntar aquí.

¿Es posible para mí determinar qué SQL se ejecutó que hizo que se utilizaran los índices anteriores? Por ejemplo, si uno de los índices informados tiene 10 User_Seeks, ¿sería posible determinar que exec sp_1 causó ese uso 7 veces y exec sp_2 causó ese uso 3 veces?

Respuesta

2

Editar (de nuevo, después de la actualización pregunta):

No hay posibilidad realista. Puede probar profiler y capturar el plan de texto. Vi esto una vez y mató a un servidor: es mucho texto para grabar. YMMV :-)

Los procedimientos almacenados no usan índices.

procedimientos almacenados utilizan tablas (y vistas indizadas) que continuación índices de uso (o no use como usted ha trabajado anteriormente)

Haciendo SELECT col1, col2 FROM myTable WHERE col2 = 'foo' ORDER BY col1 es la misma ya sea en un procedimiento almacenado, vista , función definida por el usuario o solo.

Editar: Nuestro script uso del índice, descargado de algún sitio ...

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

. Bueno, me tienes ahí gbn. ¿Te gustaría que reformulara mi pregunta o entiendes el espíritu de lo que trato de decir? –

+0

Tendrá que volver a formular ... porque los procesos almacenados todavía no usarán índices ... – gbn

+3

Abe, esto puede parecer pedante, pero hay buenas razones para ser claro en la comunicación sobre temas técnicos como este. Una de las razones es '¿quieres la respuesta correcta?' – DaveE

0

En el estudio de administración SQL, puede ver exactamente cómo se ejecuta la consulta utilizando la opción "Mostrar plan de ejecución" en el menú Consulta.

+1

Lo sé, pero si tengo 100 procedimientos almacenados prefiero no examinar cada uno de ellos y encontrar esta información manualmente. Lo que estoy tratando de averiguar es si hay una tabla del sistema o una vista que pueda consultar para averiguar qué índices usan los procs –

0

no tengo acceso a SQL Management Studio en casa, pero a lo mejor se puede ver en las dependencias procdures almacenados (es decir this procedimiento de almacenamiento depende de estas tablas y por lo tanto puede utilizar estos índices)

This page podría darle alguna pista, como el uso de la tabla INFORMATION_SCHEMA.ROUTINES sistema:

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

Puede completar esta información en una tabla temporal y luego usarla para consultar los índices utilizados, mirando las estadísticas de uso del índice.

sentimos que no soy capaz de darle un ejemplo práctico, sólo un ejemplo teórico ...

+0

nunca use INFORMATION_SCHEMA.ROUTINES. Siempre use sys.sql_modules. ROUTINE_DEFINITION es nvarchar (4000): puedes averiguar por qué se rompe esto ... – gbn

2

que tiene el número de ejecuciones de todas las declaraciones en sys.dm_exec_query_stats, y se puede extraer el plan de XML usando sys.dm_exec_query_plan. El plan contiene detalles como los operadores de exploración utilizados, por lo que entre estos dos puede hacer una gran cantidad de información a partir de lo que pregunta.Por ejemplo, la siguiente consulta que mostrará los operadores INDEXSCAN en los estados ejecutar con frecuencia a partir de los planes almacenados en caché que están causando muchas lecturas lógicas:

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

Dado un nombre de índice, esto devolverá toda la definición de cada proc (en "entire_query") y la instrucción SQL real en ese proceso que usa el índice (en "consulta"). Tenga en cuenta que corre muy lentamente!

declare @indexName nvarchar(255) = N'[IX_Transaction_TypeId_TranId_StatusId]' 

;with xmlnamespaces ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sp) 
select 
    n.value(N'@Index', N'sysname') as IndexName, 
    replace(t.text, '**', '') as entire_query, 
    substring (t.text,(s.statement_start_offset/2) + 1, 
      ((case when s.statement_end_offset = -1 then len(convert(nvarchar(max), t.text)) * 2 
     else 
      s.statement_end_offset 
     end 
     - s.statement_start_offset)/2) + 1) as query, 
    p.query_plan 
from 
    sys.dm_exec_query_stats as s 
    cross apply sys.dm_exec_sql_text(s.sql_handle) as t 
    cross apply sys.dm_exec_query_plan(s.plan_handle) as p 
    cross apply query_plan.nodes('//sp:Object') as p1(n) 
where 
    n.value(N'@Index', N'sysname') = @indexName 
Cuestiones relacionadas