150 ~ 200 のストアド プロシージャを含む SQL Server DB があり、1 つを除いてすべてが 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 で使用されるまでに時間の遅延がある場合、この状態が発生する可能性があります。
- 一括操作ステートメントやサイズが 8 KB を超える文字列リテラルを含むステートメントなど、一部の Transact-SQL ステートメントはキャッシュされません。このようなステートメントの XML プラン表示は、キャッシュに存在しないため、バッチが現在実行されていない限り、sys.dm_exec_query_plan を使用して取得できません。
- Transact-SQL バッチまたはストアド プロシージャに、EXEC (文字列) などを使用したユーザー定義関数の呼び出しまたは動的 SQL の呼び出しが含まれている場合、ユーザー定義関数のコンパイル済み XML プラン表示は、返されるテーブルに含まれません。バッチまたはストアド プロシージャの sys.dm_exec_query_plan によって。代わりに、ユーザー定義関数に対応するプラン ハンドルの sys.dm_exec_query_plan を個別に呼び出す必要があります。
以降..
xml データ型で許可されるネストされたレベルの数の制限により、sys.dm_exec_query_plan は、ネストされた要素の 128 レベル以上のクエリ プランを返すことができません。
これらのどれもこの手順には当てはまらないと確信しています。どのようなタイミングであっても、結果にはクエリ プランがないため、1 は適用されません。長い文字列リテラルや一括操作がないため、2 は適用されません。ユーザー定義関数や動的 SQL がないため、3 は適用されません。そして入れ子はほとんどないので、最後のものは当てはまりません。実際、これは非常に単純な proc であり、完全に含まれています (問題のない人を保護するためにいくつかのテーブル名が変更されています)。パラメータ スニッフィングの悪ふざけは、問題の日付よりも古いことに注意してください。クエリでパラメーターを直接使用しても、引き続き発生します。この 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