Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Quelles sont les principales différences entre OPTION(OPTIMIZE FOR UNKNOWN) et OPTION(RECOMPILE) ?

Oui, ce sera le cas.

Il existe deux différences principales entre OPTION(OPTIMIZE FOR UNKNOWN) et OPTION(RECOMPILE) comme on peut le voir à partir de cette citation de MSDN :

Ainsi, les deux principales différences sont :

  1. Mise en cache (ou non) du plan de requête.

Généralement, le plan de requête généré est mis en cache et réutilisé. OPTIMIZE FOR UNKNOWN n'affecte pas cette caractéristique du moteur. RECOMPILE supprime cette fonctionnalité et indique au moteur de supprimer le plan et de ne pas le mettre dans le cache.

  1. Utiliser (ou non) les valeurs réelles des paramètres lors de la génération du plan.

Habituellement, l'optimiseur "renifle" les valeurs des paramètres et utilise ces valeurs lors de la génération du plan. OPTIMIZE FOR UNKNOWN supprime cette fonctionnalité et indique au moteur de traiter tous les paramètres comme si leurs valeurs étaient inconnues. Optimizer intègre des règles et des heuristiques permettant d'utiliser les statistiques disponibles pour divers critères de filtrage. Voir Optimiser pour… Médiocre ? pour plus de détails. Normalement, le reniflage de paramètres est utilisé lors de la première exécution de la requête/procédure stockée et utilise les valeurs des paramètres lors de la première exécution. Le plan généré est mis en cache et peut être réutilisé ultérieurement.

Une chose non évidente à retenir ici est que dans les deux cas (normal sans aucun indice de requête et avec OPTIMIZE FOR UNKNOWN indice) le plan généré doit être valide et produire un résultat correct pour tout valeur de paramètre possible. Il est adapté aux valeurs reniflées qui ont été utilisées lors de la première exécution dans le cas normal/sans indice ; il n'est adapté à aucune valeur spécifique dans le OPTIMIZE FOR UNKNOWN cas, mais il est toujours valable si le paramètre change ultérieurement de quelque manière que ce soit.

Ceci est important et empêche l'optimiseur d'effectuer certaines transformations et simplifications du plan.

OPTION(RECOMPILE) permet à l'optimiseur d'aligner les valeurs réelles des paramètres lors de chaque exécution et l'optimiseur utilise les valeurs réelles des paramètres pour générer un meilleur plan. Il n'a pas à craindre que le plan généré ne fonctionne pas avec une autre valeur de paramètre, car le plan ne sera pas mis en cache et réutilisé.

Cet effet est surtout visible pour les Conditions de recherche dynamiques requêtes. Par exemple :

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)

Si @ParamSomeID est 0 l'optimiseur traiterait la requête comme si elle n'avait pas de WHERE clause du tout. Le plan ne mentionnerait pas OtherTable du tout.

Si @ParamSomeID est -1 , le plan rejoindrait T vers OtherTable en utilisant Left Anti Semi Join et analyserait l'ensemble de OtherTable .

Si @ParamSomeID est, disons, 5, le plan ferait une recherche d'index dans l'index unique sur OtherTable et lire une seule ligne de OtherTable .

Sans OPTION(RECOMPILE) ce genre de simplification et de transformation ne se produirait pas.

Une autre raison d'utiliser OPTION(RECOMPILE) c'est quand la distribution de vos données est très asymétrique. Par exemple, vous avez une table avec 1 million de lignes. Une colonne a la valeur 0 dans 990K lignes et les valeurs de 1 à 10 dans 1K lignes. Les requêtes qui filtrent sur cette colonne doivent avoir des plans différents en fonction de la valeur réelle du filtre.

Dans les deux exemples ci-dessus OPTIMIZE FOR UNKNOWN générerait un plan médiocre.