Ano, bude.
Mezi OPTION(OPTIMIZE FOR UNKNOWN)
jsou dva hlavní rozdíly a OPTION(RECOMPILE)
jak je vidět z tohoto citátu z MSDN
:
Takže dva hlavní rozdíly jsou:
- Ukládání (nebo neukládání) plánu dotazů do mezipaměti.
Obvykle je vygenerovaný plán dotazů uložen do mezipaměti a znovu použit. OPTIMIZE FOR UNKNOWN
neovlivňuje tuto vlastnost motoru. RECOMPILE
potlačí tuto funkci a řekne enginu, aby zahodil plán a nevkládal ho do mezipaměti.
- Použití (nebo ne) skutečných hodnot parametrů během generování plánu.
Optimalizátor obvykle „načuchá“ hodnoty parametrů a použije je při generování plánu. OPTIMIZE FOR UNKNOWN
potlačí tuto funkci a řekne motoru, aby zacházel se všemi parametry, jako by jejich hodnoty byly neznámé. Optimalizátor má vestavěná pravidla a heuristiku, jak používat dostupné statistiky pro různá kritéria filtrování. Viz Optimalizace pro… Průměrná?
Více podrobností. Normálně se sniffing parametrů používá při prvním spuštění dotazu/uložené procedury a používá hodnoty parametrů během prvního spuštění. Vygenerovaný plán je uložen do mezipaměti a později jej lze znovu použít.
Jedna nezřejmá věc, kterou je třeba si pamatovat, je, že v obou případech (normální bez jakýchkoliv dotazů a s OPTIMIZE FOR UNKNOWN
hint) vygenerovaný plán musí být platný a musí poskytovat správný výsledek pro jakýkoli možná hodnota parametru. Je přizpůsoben načteným hodnotám, které byly použity při prvním spuštění v případě normálního/bez náznaku; není přizpůsoben žádné konkrétní hodnotě v OPTIMIZE FOR UNKNOWN
případ, ale je stále platný, pokud se parametr později jakýmkoli způsobem změní.
To je významné a zabraňuje to optimalizátoru provádět určité transformace a zjednodušení plánu.
OPTION(RECOMPILE)
umožňuje optimalizátoru vkládat skutečné hodnoty parametrů během každého běhu a optimalizátor používá skutečné hodnoty parametrů k vytvoření lepšího plánu. Nemusí se bát, že vygenerovaný plán nemusí fungovat s nějakou jinou hodnotou parametru, protože plán nebude uložen do mezipaměti a znovu použit.
Tento efekt je většinou viditelný pro podmínky dynamického vyhledávání dotazy. Například:
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)
Pokud @ParamSomeID
je 0
Optimalizátor by zacházel s dotazem, jako by neměl žádné WHERE
klauzule vůbec. Plán by nezmiňoval OtherTable
vůbec.
Pokud @ParamSomeID
je -1
, plán by se připojil k T
do OtherTable
pomocí Left Anti Semi Join a naskenuje celou OtherTable
.
Pokud @ParamSomeID
je, řekněme, 5, plán by provedl hledání indexu v jedinečném indexu na OtherTable
a číst pouze jeden řádek z OtherTable
.
Bez OPTION(RECOMPILE)
k takovému zjednodušení a transformaci by nedošlo.
Další důvod, proč použít OPTION(RECOMPILE)
když je distribuce dat velmi zkreslená. Máte například tabulku s 1 milionem řádků. Jeden sloupec má hodnotu 0 v 990 000 řádcích a hodnoty od 1 do 10 v 1 000 řádcích. Dotazy, které filtrují v tomto sloupci, by měly mít různé plány v závislosti na skutečné hodnotě filtru.
V obou výše uvedených příkladech OPTIMIZE FOR UNKNOWN
by vytvořil průměrný plán.