Tak, będzie.
Istnieją dwie główne różnice między OPTION(OPTIMIZE FOR UNKNOWN)
i OPTION(RECOMPILE)
jak widać z tego cytatu z MSDN
:
Tak więc dwie główne różnice to:
- Buforowanie (lub nie) planu zapytań.
Zwykle wygenerowany plan zapytania jest buforowany i ponownie używany. OPTIMIZE FOR UNKNOWN
nie wpływa na tę funkcję silnika. RECOMPILE
wyłącza tę funkcję i mówi silnikowi, aby odrzucił plan i nie umieszczał go w pamięci podręcznej.
- Używanie (lub nie) rzeczywistych wartości parametrów podczas generowania planu.
Zwykle optymalizator „wyszukuje” wartości parametrów i używa ich podczas generowania planu. OPTIMIZE FOR UNKNOWN
wyłącza tę funkcję i mówi silnikowi, aby traktował wszystkie parametry tak, jakby ich wartości były nieznane. Optymalizator ma wbudowane reguły i heurystykę, jak korzystać z dostępnych statystyk dla różnych kryteriów filtrowania. Zobacz Optymalizuj pod kątem… przeciętnego?
po więcej szczegółów. Zwykle wąchanie parametrów jest używane przy pierwszym uruchomieniu zapytania/procedury składowanej i wykorzystuje wartości parametrów podczas pierwszego uruchomienia. Wygenerowany plan jest buforowany i później można go ponownie wykorzystać.
Jedną nieoczywistą rzeczą, o której należy pamiętać, jest to, że w obu przypadkach (normalnie bez podpowiedzi dotyczących zapytań i z OPTIMIZE FOR UNKNOWN
wskazówka) wygenerowany plan musi być prawidłowy i dawać poprawny wynik dla dowolnego możliwa wartość parametru. Jest on dostosowany do wąchanych wartości, które zostały użyte podczas pierwszego przebiegu w przypadku normalnym/bez podpowiedzi; nie jest dostosowany do żadnej określonej wartości w OPTIMIZE FOR UNKNOWN
przypadku, ale nadal obowiązuje, jeśli parametr zmieni się później w jakikolwiek sposób.
Jest to istotne i uniemożliwia optymalizatorowi wykonanie pewnych przekształceń i uproszczeń planu.
OPTION(RECOMPILE)
umożliwia optymalizatorowi wbudowanie rzeczywistych wartości parametrów podczas każdego uruchomienia, a optymalizator wykorzystuje rzeczywiste wartości parametrów do generowania lepszego planu. Nie musi się martwić, że wygenerowany plan może nie działać z inną wartością parametru, ponieważ plan nie zostanie zapisany w pamięci podręcznej i ponownie wykorzystany.
Ten efekt jest najbardziej widoczny w przypadku dynamicznych warunków wyszukiwania zapytania. Na przykład:
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)
Jeśli @ParamSomeID
to 0
optymalizator potraktuje zapytanie tak, jakby nie miało żadnego WHERE
w ogóle. Plan nie wspominał o OtherTable
w ogóle.
Jeśli @ParamSomeID
to -1
, plan dołączyłby do T
do OtherTable
używając Left Anti Semi Join i zeskanowałby całą OtherTable
.
Jeśli @ParamSomeID
to powiedzmy 5, plan wykonałby wyszukiwanie indeksu w unikalnym indeksie na OtherTable
i przeczytaj tylko jeden wiersz z OtherTable
.
Bez OPTION(RECOMPILE)
tego rodzaju uproszczenie i przekształcenie nie miałoby miejsca.
Kolejny powód, aby użyć OPTION(RECOMPILE)
to sytuacja, w której dystrybucja danych jest bardzo zniekształcona. Na przykład masz tabelę z 1 mln wierszy. Jedna kolumna ma wartość 0 w 990 tys. wierszy i wartości od 1 do 10 w 1 tys. wierszy. Zapytania filtrujące w tej kolumnie powinny mieć różne plany w zależności od rzeczywistej wartości filtra.
W obu powyższych przykładach OPTIMIZE FOR UNKNOWN
wygenerowałby przeciętny plan.