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

发布于 2024-08-24 03:08:26 字数 2435 浏览 8 评论 0原文

我们有一个包含 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 列为 null。例如,如果捕获计划句柄与将其与 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

We have a SQL Server DB with 150-200 stored procs, all of which produce a viewable query plan in sys.dm_exec_query_plan except for one. According to http://msdn.microsoft.com/en-us/library/ms189747.aspx:

Under the following conditions, no Showplan output is returned in the query_plan column of the returned table for sys.dm_exec_query_plan:

  • If the query plan that is specified by using plan_handle has been evicted from the plan cache, the query_plan column of the returned table is null. For example, this condition may occur if there is a time delay between when the plan handle was captured and when it was used with sys.dm_exec_query_plan.
  • Some Transact-SQL statements are not cached, such as bulk operation statements or statements containing string literals larger than 8 KB in size. XML Showplans for such statements cannot be retrieved by using sys.dm_exec_query_plan unless the batch is currently executing because they do not exist in the cache.
  • If a Transact-SQL batch or stored procedure contains a call to a user-defined function or a call to dynamic SQL, for example using EXEC (string), the compiled XML Showplan for the user-defined function is not included in the table returned by sys.dm_exec_query_plan for the batch or stored procedure. Instead, you must make a separate call to sys.dm_exec_query_plan for the plan handle that corresponds to the user-defined function.

And later..

Due to a limitation in the number of nested levels allowed in the xml data type, sys.dm_exec_query_plan cannot return query plans that meet or exceed 128 levels of nested elements.

I'm confident that none of these apply to this procedure. The result never has a query plan, no matter what the timing, so 1 doesn't apply. There are no long string literals or bulk operations, so 2 doesn't apply. There are no user defined functions or dynamic SQL, so 3 doesn't apply. And there's little nesting, so the last doesn't apply. In fact, it's a very simple proc, which I'm including in full (with some table names changed to protect the innocent). Note that the parameter-sniffing shenanigans postdate the problem. It still happens even if I use the parameters directly in the query. Any ideas on why I don't have a viewable query plan for this proc?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小清晰的声音 2024-08-31 03:08:26

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

Hmm, perhaps the tables aren't really tables. They could be views or something else.

粉红×色少女 2024-08-31 03:08:26

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

请参阅这篇文章:

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

引用文章中的内容:

如你所见,我引用了所有表格
用两部分表示法。也就是说,我也
指定模式(在 SQL 中
通常引用 7/2000 说法
作为所有者。)如果我省略
schema,每个用户都会有自己的
他自己的私人版本的查询
计划

try putting dbo. or whatever the schema is in front of all of the table names, and then check again.

see this article:

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

quote from the article:

As you can see, I refer to all tables
in two-part notation. That is, I also
specify the schema (which in SQL
7/2000 parlance normally is referred
to as owner.) If I would leave out the
schema, each user would get his own
his own private version of the query
plan

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文