Ja, det kommer det.
Det finns två huvudsakliga skillnader mellan OPTION(OPTIMIZE FOR UNKNOWN)
och OPTION(RECOMPILE)
som framgår av detta citat från MSDN
:
Så de två huvudsakliga skillnaderna är:
- Cachning (eller inte) av frågeplanen.
Vanligtvis cachelagras den genererade frågeplanen och återanvänds. OPTIMIZE FOR UNKNOWN
påverkar inte denna funktion hos motorn. RECOMPILE
undertrycker denna funktion och säger åt motorn att kassera planen och inte lägga den i cachen.
- Använda (eller inte) faktiska parametervärden under plangenerering.
Vanligtvis "sniffar" optimeraren parametervärdena och använder dessa värden när planen genereras. OPTIMIZE FOR UNKNOWN
undertrycker denna funktion och säger åt motorn att behandla alla parametrar som om deras värden var okända. Optimizer har inbyggda regler och heuristik hur man använder tillgänglig statistik för olika filtreringskriterier. Se Optimera för... Medelmåttig?
för mer detaljer. Normalt används parametersniffning vid den första körningen av frågan/lagrade proceduren och använder parametrarnas värden under den första körningen. Den genererade planen cachelagras och kan senare återanvändas.
En icke-uppenbar sak att komma ihåg här är att i båda fallen (normalt utan några frågetips och med OPTIMIZE FOR UNKNOWN
ledtråd) måste den genererade planen vara giltig och ge korrekt resultat för alla möjligt parametervärde. Den är skräddarsydd för de sniffade värdena som användes under den första körningen i fallet med normal/ingen antydan; den är inte anpassad till något specifikt värde i OPTIMIZE FOR UNKNOWN
fall, men det är fortfarande giltigt om parametern ändras senare på något sätt.
Detta är viktigt och det hindrar optimeraren från att utföra vissa transformationer och förenklingar av planen.
OPTION(RECOMPILE)
tillåter optimeraren att infoga de faktiska parametrarnas värden under varje körning och optimeraren använder de faktiska parametrarnas värden för att skapa en bättre plan. Det behöver inte oroa dig för att den genererade planen kanske inte fungerar med något annat parametervärde, eftersom planen inte kommer att cachelagras och återanvändas.
Denna effekt är mest synlig för Dynamiska sökvillkor frågor. Till exempel:
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)
Om @ParamSomeID
är 0
Optimizer skulle behandla frågan som om den inte hade någon WHERE
klausul överhuvudtaget. Planen skulle inte nämna OtherTable
alls.
Om @ParamSomeID
är -1
, skulle planen gå med i T
till OtherTable
genom att använda Left Anti Semi Join och skanna hela OtherTable
.
Om @ParamSomeID
är, säg, 5, skulle planen göra en indexsökning i unikt index på OtherTable
och läs endast en rad från OtherTable
.
Utan OPTION(RECOMPILE)
denna typ av förenkling och omvandling skulle inte ske.
Ytterligare ett skäl att använda OPTION(RECOMPILE)
är när din datadistribution är väldigt skev. Till exempel har du en tabell med 1M rader. En kolumn har värde 0 i 990 000 rader och värden från 1 till 10 i 1 000 rader. Frågorna som filtrerar på den här kolumnen bör ha olika planer beroende på filtrets faktiska värde.
I båda exemplen ovan OPTIMIZE FOR UNKNOWN
skulle generera en medioker plan.