Да, ще стане.
Има две основни разлики между OPTION(OPTIMIZE FOR UNKNOWN)
и OPTION(RECOMPILE)
както може да се види от този цитат от MSDN
:
И така, двете основни разлики са:
- Кеширане (или не) на плана на заявката.
Обикновено генерираният план за заявка се кешира и използва повторно. OPTIMIZE FOR UNKNOWN
не засяга тази характеристика на двигателя. RECOMPILE
потиска тази функция и казва на двигателя да отхвърли плана и да не го поставя в кеша.
- Използване (или не) на действителни стойности на параметри по време на генериране на план.
Обикновено оптимизаторът "надушва" стойностите на параметрите и ги използва при генериране на плана. OPTIMIZE FOR UNKNOWN
потиска тази функция и казва на двигателя да третира всички параметри, сякаш стойностите им са неизвестни. Оптимизаторът има вградени правила и евристики как да използва наличната статистика за различни критерии за филтриране. Вижте Оптимизиране за... Посредствено?
за повече информация. Обикновено снифирането на параметри се използва при първото изпълнение на заявката/съхранената процедура и използва стойностите на параметрите по време на първото изпълнение. Генерираният план се кешира и по-късно може да се използва повторно.
Едно неочевидно нещо, което трябва да запомните тук, е, че и в двата случая (нормално без подсказки за заявка и с OPTIMIZE FOR UNKNOWN
намек) генерираният план трябва да е валиден и да дава правилен резултат за всеки възможна стойност на параметъра. Той е съобразен с надушените стойности, които са били използвани по време на първото изпълнение в случай нормален/без намек; не е съобразено с конкретна стойност в OPTIMIZE FOR UNKNOWN
случай, но все още е валиден, ако параметърът се промени по-късно по някакъв начин.
Това е важно и не позволява на оптимизатора да извърши определени трансформации и опростявания на плана.
OPTION(RECOMPILE)
позволява на оптимизатора да вгражда действителните стойности на параметрите по време на всяко изпълнение и оптимизаторът използва действителните стойности на параметрите, за да генерира по-добър план. Не е нужно да се притеснявате, че генерираният план може да не работи с някаква друга стойност на параметъра, защото планът няма да бъде кеширан и използван повторно.
Този ефект е видим най-вече за Условия за динамично търсене заявки. Например:
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)
Ако @ParamSomeID
е 0
оптимизаторът ще третира заявката така, сякаш няма WHERE
клауза изобщо. В плана не се споменава OtherTable
изобщо.
Ако @ParamSomeID
е -1
, планът ще се присъедини към T
към OtherTable
използвайки Left Anti Semi Join и ще сканира цялата OtherTable
.
Ако @ParamSomeID
е, да речем, 5, планът ще извърши търсене на индекс в уникален индекс на OtherTable
и прочете само един ред от OtherTable
.
Без OPTION(RECOMPILE)
този вид опростяване и трансформация няма да се случи.
Друга причина да използвате OPTION(RECOMPILE)
е, когато разпределението на вашите данни е много изкривено. Например, имате таблица с 1M редове. Една колона има стойност 0 в 990K реда и стойности от 1 до 10 в 1K реда. Заявките, които филтрират тази колона, трябва да имат различни планове в зависимост от действителната стойност на филтъра.
И в двата примера по-горе OPTIMIZE FOR UNKNOWN
ще генерира посредствен план.