SQL Server 2005 中没有过程的查询计划
我们有一个包含 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
嗯,也许这些桌子并不是真正的桌子。它们可以是视图或其他东西。
Hmm, perhaps the tables aren't really tables. They could be views or something else.
尝试将 dbo. 或任何架构放在所有表名称的前面,然后再次检查。
请参阅这篇文章:
http://www.sommarskog.se/dyn-search-2005。 html
引用文章中的内容:
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: