J'ai deux requêtes presque identiques à exécuter sur la même instance SQL Server 2005:
SELECT
générée par Linq (je sais, je sais ... Je ne suis pas le développeur d'applications, juste le DBA :).OPTION (RECOMPILE)
à la fin.Rien d'autre n'a été changé.
Le premier prend 55 secondes à chaque fois sa course.
[.____] Le second prend 2 secondes.
Les deux ensembles de résultats sont identiques.
Pourquoi cet indicateur générerait-il un gain aussi dramatique de performance?
L'entrée en ligne de livres sur RECOMPILE
_ n'offre pas une explication très détaillée:
Indique le moteur de base de données SQL Server de supprimer le plan généré pour la requête après exécution, forçant l'optimiseur de requête à recompiler un plan de requête la prochaine fois que la même requête est exécutée. Sans spécifier Recompiler, le moteur de base de données met en cache la requête planifie et les réutilise. Lors de la compilation des plans de requête, l'indice de requête recompilé utilise les valeurs actuelles de toutes les variables locales de la requête et, si la requête est à l'intérieur d'une procédure stockée, les valeurs actuelles sont transmises à tous les paramètres.
Recompiler est une alternative utile pour créer une procédure stockée qui utilise la clause de recompilation lorsqu'un sous-ensemble de requêtes à l'intérieur de la procédure stockée, au lieu de la procédure stockée entière, doit être recompanté. Pour plus d'informations, voir Recompilation des procédures stockées. Recompiler est également utile lorsque vous créez des guides de plan. Pour plus d'informations, voir Optimisation des requêtes dans les applications déployées à l'aide de guides de plan.
Étant donné que ma requête a beaucoup de variables locales, je suppose que SQL Server est capable de l'optimiser (sérieusement) l'optimiser lorsque j'utilise le OPTION (RECOMPILE)
Requête.
Partout où je regarde, les gens disent que OPTION (RECOMPILE)
devrait être évité. L'explication de cela est généralement que l'utilisation de ce serveur SQL d'indice n'est pas en mesure de réutiliser ce plan d'exection et doit donc perdre du temps à la recompiler à chaque fois.
[.____] (mais) Compte tenu de l'avantage de la performance gigantesque, je suis enclin à penser que l'utilisation de cette question de requête cette fois serait une bonne chose.
Devrais-je l'utiliser? Sinon, est-ce que je peux forcer SQL Server à utiliser un meilleur plan d'exécution sans cette indication et sans modifier l'application?
Comme documenté dans l'article Statistiques utilisées par l'optimiseur de requêtes dans Microsoft SQL Server 2005
Si vous utilisez une variable locale dans un prédicat de requête au lieu d'un paramètre ou d'un littéral, l'optimiseur a recours à une estimation de la qualité réduite, ou une supposition pour la sélectivité du prédicat. Utilisez des paramètres ou des littéraux dans la requête au lieu de variables locales
Lorsque l'optimiseur n'a aucune statistique utilisable du tout pour une colonne, elle devra devinez qu'un prédicat =
correspondra à 10% des lignes, BETWEEN
9%, et l'une quelconque de >, >=, < and <=
correspondra à 30%. . S'il y a des statistiques de colonne disponibles, un prédicat =
sera traité différemment comme ci-dessous.
Même lorsque des variables locales sont utilisées dans une requête, une estimation meilleure qu'une hypothèse est utilisée dans le cas des prédicats d'égalité. Sélectivité pour les conditions du formulaire "
@local_variable = column_name
" est estimée à l'aide de la fréquence de valeur moyenne de l'histogramme de nom de colonne. Ainsi, par exemple, si la colonne Nom_name contient toutes les valeurs uniques, une estimation de sélectivité de1/(number of unique values in column)
sera utilisée, ce qui est précis.
C'est donc essentiellement la même chose que d'utiliser pour OPTIMIZE FOR (UNKNOWN)
. Il peut bien être plus précis qu'un appartement 10%
devinez, mais il n'est pas adapté aux valeurs spécifiques que vous interrogez.
Pour forcer SQL Server à optimiser une requête chaque fois qu'il est exécuté et utilisez les valeurs des variables locales pour estimer la cardinalité et les coûts lors de l'optimisation de la requête, ajoutez le conseil
RECOMPILE
à la requête.
Avec l'utilisation de RECOMPILE
, vous obtenez probablement des estimations de cardinalité plus précises et donc un plan différent avec les ordres de jointure/types de jointures plus adaptés au nombre de lignes retournées de différentes parties de votre requête réelle.