2

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
4

2 に答える 2

2

うーん、おそらくテーブルは実際にはテーブルではありません。それらはビューまたは何か他のものである可能性があります。

于 2010-03-02T20:07:24.157 に答える
0

dbo.またはスキーマがすべてのテーブル名の前にあるものを入れてみて、もう一度確認してください。

この記事を参照してください:

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

記事からの引用:

ご覧のとおり、すべての表を 2 部表記で参照しています。つまり、スキーマも指定します (SQL 7/2000 の用語では通常、所有者と呼ばれます)。スキーマを省略した場合、各ユーザーはクエリ プランの独自のプライベート バージョンを取得します。

于 2010-03-02T19:40:28.253 に答える