2

我们有一个带有 150-200 个存储过程的 SQL Server DB,除了一个之外,所有这些都在 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
4

2 回答 2

2

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

于 2010-03-02T20:07:24.157 回答
0

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

见这篇文章:

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

引用文章:

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

于 2010-03-02T19:40:28.253 回答