私は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を使用していることを確認しました。
ここに表示されない実行計画を取得するにはどうすればよいですか?
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
そして、これが私のサーバーからのサンプル結果です:
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_TIMEOUT
の5ms
があり、特定のプランを検索するときにロックが発生した場合に手順全体が過度に遅延するのを回避します。
--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ファイルに変換する指示で処理されているようです。