SQL Server 2005 中没有过程的查询计划

Posted

技术标签:

【中文标题】SQL Server 2005 中没有过程的查询计划【英文标题】:No query plan for procedure in SQL Server 2005 【发布时间】:2010-03-02 19:23:14 【问题描述】:

我们有一个带有 150-200 个存储过程的 SQL Server 数据库,所有这些都在 sys.dm_exec_query_plan 中生成一个可查看的查询计划,除了一个。根据http://msdn.microsoft.com/en-us/library/ms189747.aspx:

在以下情况下,sys.dm_exec_query_plan的返回表的query_plan列没有返回Showplan输出:

如果使用plan_handle 指定的查询计划已从计划缓存中逐出,则返回表的query_plan 列为空。例如,如果在捕获计划句柄和将其与 sys.dm_exec_query_plan 一起使用之间存在时间延迟,则可能会出现这种情况。 某些 Transact-SQL 语句未缓存,例如批量操作语句或包含大小大于 8 KB 的字符串文字的语句。无法使用 sys.dm_exec_query_plan 检索此类语句的 XML 显示计划,除非批处理当前正在执行,因为它们不存在于缓存中。 如果 Transact-SQL 批处理或存储过程包含对用户定义函数的调用或对动态 SQL 的调用,例如使用 EXEC(字符串),则为用户定义函数编译的 XML Showplan 不包含在sys.dm_exec_query_plan 为批处理或存储过程返回的表。相反,您必须为与用户定义函数对应的计划句柄单独调用 sys.dm_exec_query_plan。

后来……

由于 xml 数据类型中允许的嵌套层数的限制,sys.dm_exec_query_plan 无法返回满足或超过 128 层嵌套元素的查询计划。

我确信这些都不适用于此程序。结果永远不会有查询计划,无论时间如何,因此 1 不适用。没有长字符串文字或批量操作,因此 2 不适用。没有用户定义的函数或动态 SQL,因此 3 不适用。而且几乎没有嵌套,所以最后一个不适用。事实上,这是一个非常简单的过程,我将其全部包含在内(更改了一些表名以保护无辜者)。请注意,参数嗅探的恶作剧是在问题发生后出现的。即使我直接在查询中使用参数,它仍然会发生。关于为什么我没有此过程的可见查询计划的任何想法?

ALTER PROCEDURE [dbo].[spGetThreadComments] 
    @threadId int, 
    @stateCutoff int = 80, 
    @origin varchar(255) = null, 
    @includeComments bit = 1, 
    @count int = 100000
AS

if (@count is null)
begin
    select @count = 100000
end

-- copy parameters to local variables to avoid parameter sniffing
declare @threadIdL int, @stateCutoffL int, @originL varchar(255), @includeCommentsL bit, @countL int
select @threadIdL = @threadId, @stateCutoffL = @stateCutoff, @originL = @origin, @includeCommentsL = @includeComments, @countL = @count

set rowcount @countL

if (@originL = 'Foo')
begin
    select * from FooComments (nolock) where threadId = @threadId and statusCode <= @stateCutoff 
    order by isnull(parentCommentId, commentId), dateCreated
end
else
begin       
    if (@includeCommentsL = 1)
    begin
        select * from Comments (nolock) 
            where threadId = @threadIdL and statusCode <= @stateCutoffL
            order by isnull(parentCommentId, commentId), dateCreated
    end
    else
    begin
        select userId, commentId from Comments (nolock) 
            where threadId = @threadIdL and statusCode <= @stateCutoffL
            order by isnull(parentCommentId, commentId), dateCreated
    end
end

【问题讨论】:

你能得到 3 个查询中每一个的查询计划吗?那些“表”真的是调用函数的视图吗? 嘿大卫。我可以通过 dm_exec_query_stats 确认没有给我查询计划的 plan_handle 实际上正在工作,所以我不认为我只是在看一些总体计划而不是操作计划。 哎呀。好叫大卫。尽管这两个表理论上只是表,但其中一个实际上是不存在的表。 FooComment 沿途某处被删除。它没有导致运行时问题,因为该分支显然从未被使用过,但看起来缺少表正在阻止查询计划的生成和/或正确显示。如果你想把它写下来作为答案,我会给你功劳。 【参考方案1】:

嗯,也许这些表格并不是真正的表格。它们可能是视图或其他东西。

【讨论】:

我们的商店在将数据库结构从一个数据库复制到另一个数据库时遇到了很多不存在的对象。最终我们得到了一个工具来检测缺失的依赖项。 奇怪的是,在您实际执行该代码分支之前,SQL 中没有任何内容会抱怨它。似乎在某处值得警告。【参考方案2】:

尝试将dbo. 或任何架构放在所有表名的前面,然后再次检查。

见这篇文章:

http://www.sommarskog.se/dyn-search-2005.html

引用文章:

如您所见,我指的是所有表格 以两部分表示法。也就是说,我也 指定架构(在 SQL 7/2000 的说法通常被提及 作为所有者。)如果我不考虑 模式,每个用户都会得到自己的 他自己的私人查询版本 计划

【讨论】:

嘿KM。这看起来是一种很好的做法(事实上,我们确实遇到了一些问题,即 sql 跟踪会显示性能不佳的查询,而当我运行它们时运行良好。可能是每个连接都获得不同的查询计划的情况)。但在这种情况下,我们从所有 proc 中省略了完全限定名称,只有这个缺少查询计划。

以上是关于SQL Server 2005 中没有过程的查询计划的主要内容,如果未能解决你的问题,请参考以下文章

sql server 2005中有没有像oracle中(set timing on)设置查询时间的语句啊?

急急急!应用程序在sql server2005里执行的sql语句怎样查看!

如何从 Sql Server 2005 Express 版本的日志文件(.ldf)中查询?

Sql Server2005数据库怎么查看视图里的字段。

SQL Server 2005 查询多个Access 数据库?

SQL server2005上千万条数据分页查询怎么做优化?