Ja, det vil det.
Der er to hovedforskelle mellem OPTION(OPTIMIZE FOR UNKNOWN)
og OPTION(RECOMPILE)
som det kan ses af dette citat fra MSDN
:
Så de to vigtigste forskelle er:
- Caching (eller ej) af forespørgselsplanen.
Normalt cachelagres den genererede forespørgselsplan og genbruges. OPTIMIZE FOR UNKNOWN
påvirker ikke denne funktion af motoren. RECOMPILE
undertrykker denne funktion og beder motoren om at kassere planen og ikke lægge den i cachen.
- Brug (eller ej) faktiske parameterværdier under plangenerering.
Normalt "snuser" optimizer parameterværdierne og bruger disse værdier, når planen genereres. OPTIMIZE FOR UNKNOWN
undertrykker denne funktion og fortæller motoren at behandle alle parametre, som om deres værdier var ukendte. Optimizer har indbyggede regler og heuristik, hvordan man bruger tilgængelig statistik til forskellige filtreringskriterier. Se Optimer til... Middelmådig?
for flere detaljer. Normalt bruges parametersniffing ved den første kørsel af forespørgslen/den lagrede procedure og bruger værdierne af parametrene under den første kørsel. Den genererede plan cachelagres og kan senere genbruges.
En ikke-oplagt ting at huske her er, at i begge tilfælde (normalt uden nogen forespørgselstip og med OPTIMIZE FOR UNKNOWN
tip) skal den genererede plan være gyldig og give korrekte resultater for enhver mulig parameterværdi. Den er skræddersyet til de sniffede værdier, der blev brugt under den første kørsel i normal/no-hint tilfældet; den er ikke skræddersyet til nogen specifik værdi i OPTIMIZE FOR UNKNOWN
tilfælde, men det er stadig gyldigt, hvis parameter ændres senere på nogen måde.
Dette er vigtigt, og det forhindrer optimizer i at udføre visse transformationer og forenklinger af planen.
OPTION(RECOMPILE)
giver optimizer mulighed for at inline de faktiske værdier af parametre under hver kørsel, og optimizer bruger faktiske værdier af parametre til at generere en bedre plan. Det behøver ikke at bekymre dig om, at den genererede plan muligvis ikke fungerer med en anden parameterværdi, fordi planen ikke bliver cachelagret og genbrugt.
Denne effekt er for det meste synlig for dynamiske søgebetingelser forespørgsler. For eksempel:
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)
Hvis @ParamSomeID
er 0
optimizer ville behandle forespørgslen, som om den ikke havde nogen WHERE
klausul overhovedet. Planen ville ikke nævne OtherTable
overhovedet.
Hvis @ParamSomeID
er -1
, ville planen slutte sig til T
til OtherTable
ved at bruge Left Anti Semi Join og ville scanne hele OtherTable
.
Hvis @ParamSomeID
er f.eks. 5, ville planen lave en indekssøgning i unikt indeks på OtherTable
og læs kun én række fra OtherTable
.
Uden OPTION(RECOMPILE)
denne form for forenkling og transformation ville ikke ske.
Endnu en grund til at bruge OPTION(RECOMPILE)
er, når din datafordeling er meget skæv. For eksempel har du en tabel med 1M rækker. En kolonne har værdi 0 i 990.000 rækker og værdier fra 1 til 10 i 1.000 rækker. De forespørgsler, der filtrerer på denne kolonne, bør have forskellige planer afhængigt af den faktiske værdi af filteret.
I begge eksempler ovenfor OPTIMIZE FOR UNKNOWN
ville generere en middelmådig plan.