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.