0

我有一个运行 SQL 查询的 .NET 客户端应用程序,并且该查询偶尔会被 ADO.NET 超时。超时时,我看不到 dm_exec_query_stats 中缓存的查询计划。如果查询完成,则计划缓存。

在我的应用程序异常处理程序中,我想以编程方式捕获超时的特定查询类的查询计划 - 这将帮助我进行故障排除。这可能吗?由于每个可能超时的查询都引用了一个具有唯一名称的表,因此我可以扫描查询文本以找到合适的计划。

我希望在我的异常处理程序中能够运行:

SELECT TOP 1 p.query_plan, t.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text (qs.plan_handle) AS t
CROSS APPLY sys.dm_exec_query_plan (qs.plan_handle) AS p
WHERE t.text LIKE '%UNIQUETABLE%'
ORDER BY last_execution_time DESC;

但这不包含我正在寻找的查询 - 大概是因为它已超时?

是否可以检索用于启动然后被中止的查询的查询计划?

(正在执行的 SQL 是动态的;使用存储过程会更轻松,但遗憾的是它不可用!)

4

2 回答 2

1

您的数据库是否可能针对临时工作负载进行了优化?

sp_CONFIGURE 'optimize for ad hoc workloads'
于 2013-09-26T14:48:00.067 回答
1

这将为您提供查询计划:

SELECT cplan.usecounts, 
       cplan.objtype, 
       qtext.text, 
       qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
     CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
     CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
     WHERE qtext.text LIKE '%UniqueName%'
ORDER BY cplan.usecounts DESC;

在这里你可以列出那些超时的:

WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan'),  QueryPlans 
AS  ( 
SELECT  RelOp.pln.value(N'@StatementOptmEarlyAbortReason', N'varchar(50)') AS TerminationReason, 
        RelOp.pln.value(N'@StatementOptmLevel', N'varchar(50)') AS OptimizationLevel, 
        --dest.text, 
        SUBSTRING(dest.text, (deqs.statement_start_offset / 2) + 1, 
                  (deqs.statement_end_offset - deqs.statement_start_offset) 
                  / 2 + 1) AS StatementText, 
        deqp.query_plan, 
        deqp.dbid, 
        deqs.execution_count, 
        deqs.total_elapsed_time, 
        deqs.total_logical_reads, 
        deqs.total_logical_writes 
FROM    sys.dm_exec_query_stats AS deqs 
        CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest 
        CROSS APPLY sys.dm_exec_query_plan(deqs.plan_handle) AS deqp 
        CROSS APPLY deqp.query_plan.nodes(N'//StmtSimple') RelOp (pln) 
WHERE   deqs.statement_end_offset > -1        
)   
SELECT  DB_NAME(qp.dbid), 
        * 
FROM    QueryPlans AS qp 
WHERE   qp.TerminationReason = 'Timeout' 
ORDER BY qp.execution_count DESC ;
于 2020-10-13T13:46:59.090 回答