Dan*_*ink 1 sql-server-2008 index-tuning
我一直在审查我们数据库中的索引(添加缺失的索引并删除坏的索引)。我偶然发现了我几个月前创建的一个索引,它看起来不错。自上次服务器重启(大约 2 周前)以来,只有 109 次写入,但有近 270 万次读取。通常,当我看到读取次数多于写入次数时,我会认为它是一项不错的工作,然后继续进行下一项工作,但这一次看起来好得令人难以置信。
所以我的问题是:有没有办法确定哪些存储过程正在使用索引?除了手动阅读所有存储过程并检查连接和 where 条件。
我无法完全让Jonathan 的 XML 查询为我提取它,但我能够通过以简单的方式解析 showplan_text 来获取它。这是使用AdventureWorks2012
和发出查询后Sales.SalesOrderHeader
:
DECLARE @Index SYSNAME = N'PK_SalesOrderHeader_SalesOrderID';
SELECT t.[text], s.execution_count, CONVERT(XML, p.query_plan)
FROM sys.dm_exec_query_stats AS s
CROSS APPLY sys.dm_exec_text_query_plan
(
s.plan_handle, s.statement_start_offset, s.statement_end_offset
) AS p
CROSS APPLY sys.dm_exec_sql_text(s.plan_handle) AS t
WHERE p.query_plan LIKE '%Index="\[' + @Index + '\]"%' ESCAPE '\';
Run Code Online (Sandbox Code Playgroud)
结果:
要专门获取存储过程名称(对于那些不是临时发出的查询),您需要确保您处于数据库的上下文中,然后将此列添加到上述查询的输出列表中:
, obj = QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid))
+ '.' + QUOTENAME(OBJECT_NAME(t.objectid))
Run Code Online (Sandbox Code Playgroud)
此列将NULL
用于任何临时查询。
一旦查询计划出现在结果窗格中,您当然可以单击 XML 以加载图形计划。然后,如果您安装了SentryOne 计划资源管理器和 SSMS 加载项,则可以右键单击图形计划以在计划资源管理器中查看。
请注意,该查询不会返回从另一个数据库发出的查询的结果,因此您应该在可能与目标数据库结合使用的任何数据库的上下文中重复该查询。
相比之下,Jonathan 的查询应该能够检索计划缓存中引用具有指定名称的任何索引(可能有多个)的查询。您可以进一步过滤以仅查找对这个特定的引用,即使这些查询源自其他数据库。