現象
テーブル変数に多数の行を設定してから他のテーブルと結合すると、クエリ オプティマイザーによって非効率的なクエリ プランが選択され、クエリのパフォーマンスが低下する可能性があります。
解決策
この修正プログラムを適用した後、トレース フラグ 2453 を有効にして、十分な数の行が変更されたときにテーブル変数が再コンパイルをトリガーできるようにします。 これにより、クエリ オプティマイザーがより効率的なプランを選択できる場合があります。
この問題は、次の累積的な更新プログラムまたは Service Pack for SQL Serverで最初に修正されました。
SQL Server 2014 /en-us/help/2984923 の累積的な更新プログラム 3
SQL Server 用の累積的な更新プログラムについて
SQL Serverの各新しい累積的な更新プログラムには、すべての修正プログラムと、以前の累積的な更新プログラムに含まれていたすべてのセキュリティ修正プログラムが含まれています。 SQL Serverの最新の累積的な更新プログラムを確認してください。
SQL Server 2012 用 Service Pack 2
SQL Serverのサービス パックについて
Service Pack は累積的であり、 最新の Service Pack には新しい修正プログラムと共に、それ以前の Service Pack に含まれていたすべての修正プログラムが含まれています。 このサービス パックの最新の Service Pack と最新の累積的な更新プログラムを適用することをお勧めします。 最新の Service Pack をインストールする前に、以前の Service Pack をインストールする必要はありません。 最新の Service Pack と最新の累積的な更新プログラムの詳細については、次の記事の表 1 を参照してください。
SQL Serverとそのコンポーネントのバージョン、エディション、および更新レベルを決定する方法
追加情報
バッチまたはプロシージャでテーブル変数を使用すると、クエリがコンパイルされ、テーブル変数の最初の空の状態に合わせて最適化されます。 実行時にこのテーブル変数に多数の行が設定されている場合、コンパイル済みのクエリ プランが最適でなくなる可能性があります。 たとえば、クエリは、通常、少数の行の方が効率的であるため、入れ子になったループでテーブル変数を結合している可能性があります。 テーブル変数に何百万もの行がある場合、このクエリ プランは非効率的になる可能性があります。 このような条件では、ハッシュ結合の方が適している可能性があります。 新しいクエリ プランを取得するには、再コンパイルする必要があります。 ただし、他のユーザーテーブルや一時テーブルとは異なり、テーブル変数の行数の変更ではクエリの再コンパイルはトリガーされません。 通常は、独自のオーバーヘッド コストがある OPTION (RECOMPILE) を使用してこれを回避できます。
トレース フラグ 2453 を使用すると、OPTION (RECOMPILE) なしでクエリを再コンパイルできます。 このトレース フラグは、OPTION (RECOMPILE) とは 2 つの主な側面で異なります。
(1) 他のテーブルと同じ行数のしきい値を使用します。 OPTION (RECOMPILE) とは異なり、すべての実行に対してクエリをコンパイルする必要はありません。 行数の変更が定義済みのしきい値を超えた場合にのみ、再コンパイルがトリガーされます。
(2) OPTION (RECOMPILE) により、クエリはパラメーターをピークし、クエリを最適化します。 このトレース フラグでは、パラメーターのピークは強制されません。
このトレース フラグは実行時に ON である必要があることに注意してください。 QUERYTRACEON では、このトレース フラグを使用できません。 このトレース フラグは、クエリの再コンパイルの数が増える可能性があるため、クエリの最適化の向上による節約よりもコストがかかる可能性があるため、注意して使用する必要があります。
状態
Microsoft は、これが "適用対象" セクションに記載されている Microsoft 製品の問題であることを確認しました。