Ja, das wird es.
Es gibt zwei Hauptunterschiede zwischen OPTION(OPTIMIZE FOR UNKNOWN)
und OPTION(RECOMPILE)
wie aus diesem Zitat von MSDN
ersichtlich ist :
Die beiden Hauptunterschiede sind also:
- Caching (oder nicht) des Abfrageplans.
Normalerweise wird der generierte Abfrageplan zwischengespeichert und wiederverwendet. OPTIMIZE FOR UNKNOWN
hat keinen Einfluss auf diese Funktion der Engine. RECOMPILE
unterdrückt diese Funktion und weist die Engine an, den Plan zu verwerfen und nicht in den Cache zu legen.
- Verwenden (oder nicht) tatsächlicher Parameterwerte während der Planerstellung.
Normalerweise "schnüffelt" der Optimierer die Parameterwerte und verwendet diese Werte beim Generieren des Plans. OPTIMIZE FOR UNKNOWN
unterdrückt diese Funktion und weist die Engine an, alle Parameter so zu behandeln, als ob ihre Werte unbekannt wären. Optimizer verfügt über integrierte Regeln und Heuristiken zur Verwendung verfügbarer Statistiken für verschiedene Filterkriterien. Siehe Optimieren für… Mittelmäßig?
für mehr Details. Normalerweise wird Parameter Sniffing bei der ersten Ausführung der Abfrage/gespeicherten Prozedur verwendet und verwendet die Werte der Parameter während der ersten Ausführung. Der generierte Plan wird zwischengespeichert und kann später wiederverwendet werden.
Eine nicht offensichtliche Sache, an die Sie sich hier erinnern sollten, ist, dass in beiden Fällen (normal ohne Abfragehinweise und mit OPTIMIZE FOR UNKNOWN
Hinweis) der generierte Plan muss gültig sein und für beliebige korrekte Ergebnisse liefern möglicher Parameterwert. Es ist auf die geschnüffelten Werte zugeschnitten, die während des ersten Durchlaufs im normalen/kein-Hinweis-Fall verwendet wurden; es ist nicht auf einen bestimmten Wert in OPTIMIZE FOR UNKNOWN
zugeschnitten Fall, aber es ist immer noch gültig, wenn sich der Parameter später in irgendeiner Weise ändert.
Dies ist erheblich und verhindert, dass der Optimierer bestimmte Transformationen und Vereinfachungen des Plans durchführt.
OPTION(RECOMPILE)
ermöglicht dem Optimierer, die tatsächlichen Werte der Parameter während jedes Laufs einzufügen, und der Optimierer verwendet die tatsächlichen Werte der Parameter, um einen besseren Plan zu erstellen. Es muss nicht befürchtet werden, dass der generierte Plan mit einem anderen Parameterwert nicht funktioniert, da der Plan nicht zwischengespeichert und wiederverwendet wird.
Dieser Effekt ist vor allem bei den dynamischen Suchbedingungen sichtbar Abfragen. Zum Beispiel:
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)
Wenn @ParamSomeID
ist 0
Der Optimierer würde die Abfrage so behandeln, als hätte sie kein WHERE
Klausel überhaupt. Der Plan würde OtherTable
nicht erwähnen überhaupt.
Wenn @ParamSomeID
ist -1
, würde der Plan T
beitreten zu OtherTable
mit Left Anti Semi Join und würde die gesamte OtherTable
scannen .
Wenn @ParamSomeID
beispielsweise 5 ist, würde der Plan eine Indexsuche im eindeutigen Index auf OtherTable
durchführen und lese nur eine Zeile aus OtherTable
.
Ohne OPTION(RECOMPILE)
diese Art von Vereinfachung und Transformation würde nicht stattfinden.
Ein weiterer Grund, OPTION(RECOMPILE)
zu verwenden ist, wenn Ihre Datenverteilung sehr verzerrt ist. Sie haben beispielsweise eine Tabelle mit 1 Mio. Zeilen. Eine Spalte hat den Wert 0 in 990.000 Zeilen und Werte von 1 bis 10 in 1.000 Zeilen. Die Abfragen, die nach dieser Spalte filtern, sollten abhängig vom tatsächlichen Wert des Filters unterschiedliche Pläne haben.
In beiden obigen Beispielen OPTIMIZE FOR UNKNOWN
würde einen mittelmäßigen Plan generieren.