web-dev-qa-db-ja.com

「DBCC TRACEON」と「QUERYTRACEON」の動作の違い

SQL Server 2014を使用していますが、データベースのバージョンはSQL Server 2012です。そのため、クエリオプティマイザーでカーディナリティエスティメーターv120を使用するように強制する トレースフラグ2312 を使用しています。

特定のクエリに対する独自のテストで気づきました。

  • このトレースフラグがアクティブな場合、クエリの所要時間は約20分ですが、SSMSでは20分後にすべての結果が一度に返されます
  • トレースフラグがアクティブでない場合、クエリの所要時間は約30分ですが、最初のいくつかの結果はすぐに返され、追加され続けます。

SSMSでトレースフラグに問題はありません。DBCC traceon(2312, -1)を使用してグローバルトレースフラグを設定するか、オプションoption (Querytraceon 2312)を追加するかに関係なく、トレースフラグは正しく設定されているようです。

問題は、.NETアプリケーションを介してこのクエリを実行しようとしたときに、クエリにquerytraceonオプションがある場合、クエリ全体が完了するまでIDBCommand.ExecuteReader()がハングしているようです。 SMSSでの結果を考慮してください。ただし、トレースフラグをグローバルに有効にし、クエリからquerytraceonオプションを削除すると、IDBCommand.ExecuteReader()はすぐに終了します。

私には、すべてのセッションでグローバルに有効になっているにもかかわらず、クエリがトレースフラグ2312を取得していないようです。

ここで何が矛盾を引き起こす可能性がありますか?

トレースフラグをグローバルに有効にしたプランのxml実行プランを追加しました(サイズが原因で2つの部分に分かれています)。

Querytraceonを使用して有効にしたトレースフラグの計画:(サイズが原因で2つの部分に分割)

トレースフラグが無効: https://paste.city/99

1
Steven Hsu

.NETアプリケーションから送信したクエリは、依然として「古い」プラン(レガシーのカーディナリティエスティメータを使用していた)を使用している可能性があります。

トレースフラグをグローバルに有効にしてからQUERYTRACEONヒントを削除すると、クエリテキストが異なり、新しいプランがクエリ用にコンパイルされていました。この新しくコンパイルされた計画は、新しいカーディナリティ推定器を使用したため、計画の形に関する期待に応え、結果がすぐに返されました。

この場合のクエリテキストの変更は、テスト中にSSMSにOPTION (RECOMPILE)を追加した場合と同じ効果がありました。

コメントのフォローアップ質問について:

気になるのですが、トレースフラグが有効/無効になっているときになぜこれを行う必要があるのですか?

これは、トレースフラグ2312をグローバルに有効にすると、実行プランキャッシュがクリアされないためです。したがって、新しいCEを活用する必要があるクエリの場合は、

  • これらのプランを1つずつ手動でキャッシュから削除するには( DBCC FREEPROCCACHE (plan_handle) を使用)、
  • OPTION (RECOMPILE)を一時的にそれらに追加する、または
  • プランキャッシュ全体をクリアするだけです(新しいCEを使用するためにほとんどのクエリが必要で、環境がこのアクションを処理できる場合)。
1
Josh Darnell