mvi*_*lar 2 sql-server-2005 sql-server
如何捕获或列出自上次实例重启以来使用提示并已执行的所有查询?
我使用的是 SQL Server 2005 标准版。
在我的刺激下,@buckley 已经提供了一个查询,您可以从中获取信息。我要补充的是,您可以定期捕获此 DMV 的快照,以便即使它们自上次使用以来已被推出缓存,您也可以捕获它们。我不会在这里讨论如何维护 DMV 数据的存档;也许正在制作一个很好的博客文章。
获得数据后(或仅查看缓存的当前计划),您可以从以下返回的 XML 中获得一些常见提示sys.dm_exec_query_plan.query_plan:
<QueryPlan NonParallelPlanReason="MaxDOPSetToOne"
---- this query used OPTION (MAXDOP 1) ^^^^^^^^^^^^^^
---- or perhaps was forced using server maxdop settings or resource governor
<IndexScan Ordered="0" ForcedIndex="0" ForceScan="1" NoExpandHint="0">
---- this query used WITH (FORCESCAN) ------------^
<IndexScan Ordered="0" ForcedIndex="0" ForceScan="0" NoExpandHint="1">
---- this query used WITH (NOEXPAND) ------------------------------^
<IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="1" ...>
---- this query used WITH (FORCESEEK) ------------------------------------^
<IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="1" ForceSeek="1"
---- this query uses WITH (FORCESEEK(index(col))) ----------^-------------^
<IndexScan Ordered="0" ForcedIndex="1" ForceScan="0" NoExpandHint="0">
---- this query used WITH (INDEX = ...) -^
Run Code Online (Sandbox Code Playgroud)
我不是 XML 专家,所以我不知道如何告诉您动态提取该信息。(更多关于这个下面。)
我看不到任何方法来确定是否已设置隔离(在批处理级别或使用类似的东西WITH (NOLOCK)) - 您可能必须:
sys.dm_exec_requests(尽管transaction_isolation_level实际上只告诉您诸如 之类的事情SET TRANSACTION ISOLATION LEVEL,而不是表级提示,因为您只能应用于NOLOCK查询中的某些表),或sys.dm_exec_sql_text(请注意,如果NOLOCK被注释掉,或者您有一个类似 的表名,这可能会产生误报dbo.SubmitNoLocks)。我也看不出像OPTION (FORCE ORDER)or 之类的查询提示的计划有什么不同OPTION (FAST n),因此同样地,这些提示可能还需要依赖解析查询文本,而不是依赖计划 XML。
编辑
由于您可以从备用 DMF 获得计划的非 XML 版本,因此sys.dm_exec_text_query_plan您不必成为 XML 专家来执行此解析。例如,下面将捕获缓存中的所有查询计划所用WITH (INDEX...),WITH FORCESEEK[(...)],WITH FORCESCAN,WITH (NOEXPAND)或WITH (NOLOCK):
SELECT t.[text]--, qp.query_plan
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
CROSS APPLY sys.dm_exec_text_query_plan(p.plan_handle, 0, -1) AS qp
WHERE
t.[text] NOT LIKE '%dm_exec%' -- to keep this query out of result
AND
(
qp.query_plan LIKE '%ForceSeek="1"%'
OR qp.query_plan LIKE '%Forcescan="1"%'
OR qp.query_plan LIKE '%NoExpandHint="1"%'
OR qp.query_plan LIKE '%ForcedIndex="1"%'
OR t.[text] LIKE '%NOLOCK%'
)
-- t.[dbid] = DB_ID() -- to limit results, but may be too exclusionary
;
Run Code Online (Sandbox Code Playgroud)
如前所述,这可能会对这样的查询产生误报:
SELECT * FROM dbo.table /* WITH (NOLOCK) */
SELECT * FROM dbo.RenoLocksmiths;
Run Code Online (Sandbox Code Playgroud)
但是除了解析查询文本之外NOLOCK,对于所有计划属性 - 因为 XML 被实体化并且引号之类的字符被转义 - 它不会为这样的查询返回误报:
SELECT * FROM dbo.table /* Forceseek="1" */
SELECT * FROM dbo.[WITH (FORCESEEK)];
Run Code Online (Sandbox Code Playgroud)
回想起来这是不可能的。
您需要使用SQL Profiler主动记录查询,您可以在其中导出和过滤带有提示的查询。或者使用服务器端跟踪进行长时间运行的跟踪。
您可以通过检查缓存的执行计划来接近。
这将显示大多数查询,但请记住,有些查询没有被缓存,如果有压力,sql server 可以将它们从缓存中删除。使用此查询列出它们:
SELECT [cp].[refcounts]
, [cp].[usecounts]
, [cp].[objtype]
, [st].[dbid]
, [st].[objectid]
, [st].[text]
, [qp].[query_plan]
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text ( cp.plan_handle ) st
CROSS APPLY sys.dm_exec_query_plan ( cp.plan_handle ) qp ;
Run Code Online (Sandbox Code Playgroud)
您可以将 where 子句与正则表达式(clr 函数)一起使用,以便将误报最小化到接近 0。
| 归档时间: |
|
| 查看次数: |
1125 次 |
| 最近记录: |