SQL Server 2014を使用していますが、データベースのバージョンはSQL Server 2012です。そのため、クエリオプティマイザーでカーディナリティエスティメーターv120を使用するように強制する トレースフラグ2312 を使用しています。
特定のクエリに対する独自のテストで気づきました。
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
.NETアプリケーションから送信したクエリは、依然として「古い」プラン(レガシーのカーディナリティエスティメータを使用していた)を使用している可能性があります。
トレースフラグをグローバルに有効にしてからQUERYTRACEON
ヒントを削除すると、クエリテキストが異なり、新しいプランがクエリ用にコンパイルされていました。この新しくコンパイルされた計画は、新しいカーディナリティ推定器を使用したため、計画の形に関する期待に応え、結果がすぐに返されました。
この場合のクエリテキストの変更は、テスト中にSSMSにOPTION (RECOMPILE)
を追加した場合と同じ効果がありました。
コメントのフォローアップ質問について:
気になるのですが、トレースフラグが有効/無効になっているときになぜこれを行う必要があるのですか?
これは、トレースフラグ2312をグローバルに有効にすると、実行プランキャッシュがクリアされないためです。したがって、新しいCEを活用する必要があるクエリの場合は、
DBCC FREEPROCCACHE (plan_handle)
を使用)、OPTION (RECOMPILE)
を一時的にそれらに追加する、または