はい、そうなります。
OPTION(OPTIMIZE FOR UNKNOWN)
には主に 2 つの違いがあります。 および OPTION(RECOMPILE)
MSDN
からのこの引用からわかるように :
したがって、2 つの主な違いは次のとおりです。
<オール>
通常、生成されたクエリ プランはキャッシュされ、再利用されます。 OPTIMIZE FOR UNKNOWN
エンジンのこの機能には影響しません。 RECOMPILE
この機能を抑制し、プランを破棄してキャッシュに入れないようにエンジンに指示します。
- 計画の生成中に実際のパラメータ値を使用する (または使用しない)。
通常、オプティマイザーはパラメーター値を「スニッフィング」し、プランの生成時にこれらの値を使用します。 OPTIMIZE FOR UNKNOWN
この機能を抑制し、すべてのパラメーターを値が不明であるかのように扱うようにエンジンに指示します。オプティマイザーには、さまざまなフィルタリング基準で使用可能な統計を使用する方法が組み込まれたルールとヒューリスティックがあります。 最適化を参照してください…平凡?
詳細については。通常、パラメーター スニッフィングは、クエリ/ストアド プロシージャの最初の実行時に使用され、最初の実行時にパラメーターの値を使用します。生成されたプランはキャッシュされ、後で再利用できます。
ここで覚えておかなければならないことの 1 つは、どちらの場合も (クエリ ヒントがない通常の場合と OPTIMIZE FOR UNKNOWN
がある場合) ヒント) 生成された計画は有効で、すべてのに対して正しい結果を生成する必要があります 可能なパラメータ値。通常/ヒントなしの場合の最初の実行中に使用されたスニッフィングされた値に合わせて調整されます。 OPTIMIZE FOR UNKNOWN
の特定の値に合わせて調整されていません ただし、後で何らかの方法でパラメーターが変更された場合でも有効です。
これは重要であり、オプティマイザーが計画の特定の変換と単純化を実行できなくなります。
OPTION(RECOMPILE)
各実行中にオプティマイザーがパラメーターの実際の値をインライン化できるようにし、オプティマイザーがパラメーターの実際の値を使用してより適切な計画を生成できるようにします。プランはキャッシュされず再利用されないため、生成されたプランがパラメーターの他の値で機能しない可能性があることを心配する必要はありません。
この効果は、動的検索条件 で主に見られます。 クエリ。例:
SELECT ...
FROM T
WHERE
(@ParamSomeID = 0)
OR
(
@ParamSomeID = -1
AND
T.SomeID NOT IN
(
SELECT OtherTable.SomeID
FROM OtherTable
)
)
OR
(
T.SomeID IN
(
SELECT OtherTable.SomeID
FROM OtherTable
WHERE OtherTable.SomeID = @ParamSomeID
)
)
OPTION(RECOMPILE)
If @ParamSomeID
0
です オプティマイザーは、WHERE
がないかのようにクエリを処理します。 条項はまったくありません。計画では OtherTable
について言及していません まったく。
If @ParamSomeID
-1
です 、計画は T
に参加します OtherTable
へ Left Anti Semi Join を使用すると、OtherTable
全体をスキャンします。 .
If @ParamSomeID
たとえば、5 の場合、プランは OtherTable
の一意のインデックスでインデックス シークを実行します。 OtherTable
から 1 行だけ読み取ります .
OPTION(RECOMPILE)
なし この種の単純化と変換は起こりません。
OPTION(RECOMPILE)
を使用するもう 1 つの理由 データ分布が非常に偏っている場合です。たとえば、1M 行のテーブルがあるとします。 1 つの列には、990K 行に 0 の値があり、1K 行に 1 から 10 の値があります。この列でフィルタリングするクエリは、フィルターの実際の値に応じて異なる計画を持つ必要があります。
上記の両方の例で OPTIMIZE FOR UNKNOWN
平凡な計画を生成します。