web-dev-qa-db-ja.com

実行プランがsp_WhoIsActiveに表示されないのはいつですか?

私はAdam Machanicの優れたsp_WhoIsActiveプロシージャを使用してアクティビティを確認し、長時間実行されているクエリのトラブルシューティングを行うためにテーブルにログを記録します。

実行計画が常に結果に表示されないのはなぜですか?ほとんどの場合、query_plan値がNULLです。 SQL_TEXT列が結果に表示されます。次のように、クエリにはパラメータがあり、値はありません。

(@P0 nvarchar(4000),@P1 nvarchar(4000))
select blah from foo where a = @P0 and b = @P1 

ここに表示されない実行計画を取得するにはどうすればよいですか?なぜ表示されないのですか?プロファイラーまたは拡張イベントを使用する必要がありますか?これらのパラメーターにダミー値を入力して、実際の実行プランを含めてクエリを実行すると、ログ記録時に実際に使用されたものと同じプランが生成されますか?

私はベンダーがHibernate 3.5を使用していることを確認しました。

8
SomeGuy

ここに表示されない実行計画を取得するにはどうすればよいですか?

1つのオプションは、plan_handleをキャプチャし、次のクエリを使用してそのplan_handleのクエリプランを後で検索することです。

SELECT CONVERT(XML, query_plan) from sys.dm_exec_text_query_plan(
    0x0600050059E32C0/*Truncated for brevity, replace with your full plan_handle*/,
    DEFAULT,
    DEFAULT
)

以下のplan_handleセクションのクエリを使用してReason #1をキャプチャするか、sp_whoisactiveを少し編集して結果に表示することができます。 (これは、#sessions内で使用される中間sp_whoisactiveテーブルに既にキャプチャされています)。

私がNULLクエリプランを観察したそれぞれのケースで、クエリプランはすぐに(すべてのケースで1秒未満)このメソッドを介して利用可能になりました。

これらのパラメーターにダミー値を入力し、実際の実行プランを含めてクエリを実行すると、ログ記録時に実際に使用されたものと同じプランが生成されますか?

これにより、プランがどのように見えるかがわかります。クエリプランのRetrievedFromCacheプロパティがtrueの場合、使用されていたものと同じプランが表示される可能性が高くなります。

クエリプランがsp_whoisactiveに表示されないのはなぜですか?

計画が表示されない理由は少なくともいくつか考えられますが、私はあなたが報告したのと同じ頻度でこれを観察していません。ギャップを埋める他の答えを見つけるのは興味深いでしょう。

理由#1:sys.dm_exec_requestsが-1のstatement_start_offsetを報告します

最初に、クエリプランを検索するsp_whoisactiveのセクションの簡略版を見てみましょう。

SELECT t.text,
    r.plan_handle,
    r.statement_start_offset,
    r.statement_end_offset,
    query_plan = (
        SELECT CONVERT(xml, query_plan)
        FROM sys.dm_exec_text_query_plan (
            r.plan_handle, 
            r.statement_start_offset,
            r.statement_end_offset
        )
    )
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_requests r
    ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1

そして、これが私のサーバーからのサンプル結果です:

enter image description here

documentation に基づいて、-1がsys.dm_exec_requests.statement_start_offsetの予期される値であるとは思われません。しかし、それは幾分頻繁に出現するように見え、sp_whoisactiveプロシージャはこの状況を処理しようとしません。

私のテストでは、それが可能かどうかさえわかりません。デフォルト値を使用してsys.dm_exec_text_query_planを呼び出す場合でも(オフセットに基づいて特定のプランではなく、プラン全体を見つけるため)、sys.dm_exec_requests.statement_start_offsetが-1の場合、プランが提供されないことがわかりました。

リクエストが存在する可能性はあると思いますが、プランと現在のステートメントのオフセットはまだ利用できません。ただし、この動作の完全な説明はわかりません。 plan_handleが使用可能であるため(少なくともNULLプランの場合)、プランのコンパイルがまだ行われているとは思いません。

理由#2:クエリプランを見つけるのに5ms以上かかりました

sp_whoisactiveの完全な実装では、実際にはカーソルを使用して、一度に1つずつ各プランを検索します。 LOCK_TIMEOUT5msがあり、特定のプランを検索するときにロックが発生した場合に手順全体が過度に遅延するのを回避します。

--Wait up to 5 ms for the SQL text, then give up
SET LOCK_TIMEOUT 5;
WHILE @@FETCH_STATUS = 0
...

ただし、この場合、sp_whoisactiveの出力では、<timeout_exceeded />フィールドにquery_planが表示されます。私はこれを数回見たので、NULLの値があなたの場合、理由#1である可能性が高いと思います。

理由#3:クエリプランのXMLが複雑すぎる

クエリテキストが例のように単純である場合、これはおそらくあなたの場合には思えません。ただし、XMLが複雑すぎるため、 a NULLクエリプラン が表示される可能性もあるようです。

ただし、sp_whoisactiveを見ると、このケースはメッセージCould not render showplan due to XML data type limitations.と未加工のXMLを.sqlplanファイルに変換する指示で処理されているようです。

10
Geoff Patterson