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

Définition et identification des objectifs de ligne dans les plans d'exécution

Présentation

La documentation du produit SQL Server est un peu légère sur le sujet des objectifs de ligne . Les principales références officielles se trouvent dans :

  • Conseils (Transact-SQL) – Requête (FAST et DISABLE_OPTIMIZER_ROWGOAL conseils)
  • DBCC TRACEON – Indicateurs de trace (Transact-SQL) (indicateur de trace 4138)
  • L'exécution d'une requête peut prendre beaucoup de temps si l'optimiseur de requête utilise l'opérateur Top (KB 2667211)

Lorsque les gens demandent plus d'informations que celles qui y sont contenues, je leur renvoie normalement une ou plusieurs des informations suivantes :

  • Objectifs de ligne en action par l'équipe d'optimisation des requêtes SQL Server
  • Objets de lignes revisités – Conseils FAST également par l'équipe d'optimisation des requêtes SQL Server
  • Row Goals Gone Rogue par Bart Duncan
  • À l'intérieur de l'optimiseur :rangée des objectifs en profondeur par moi
  • Le conseil de réglage SSIS qui manque à tout le monde par Rob Farley

Pour résumer brièvement :La fonctionnalité d'objectif de lignes permet à l'optimiseur de générer un plan d'exécution (ou une ou plusieurs parties d'un plan d'exécution) dans le but de retourner rapidement un certain nombre de lignes. Cela contraste avec le comportement normal (sans objectif de ligne), qui vise à trouver un plan optimisé pour l'ensemble de résultats potentiels complet.

Une stratégie d'objectif de ligne signifie généralement favoriser les opérations de navigation non bloquantes (par exemple, les jointures de boucles imbriquées, les recherches d'index et les recherches) par rapport aux opérations bloquantes basées sur des ensembles telles que le tri et le hachage. Cela peut être utile chaque fois que le client peut bénéficier d'un démarrage rapide et d'un flux régulier de lignes (avec peut-être un temps d'exécution global plus long - voir le post de Rob Farley ci-dessus). Il y a aussi les utilisations les plus évidentes et traditionnelles, par ex. en présentant les résultats une page à la fois.

Naturellement, il y a un élément de risque impliqué dans un plan d'objectifs en ligne. Si tout se déroule globalement comme prévu par l'optimiseur (compte tenu des informations disponibles et des hypothèses de modélisation formulées), le plan d'exécution commencera à diffuser le nombre de lignes demandé plus rapidement et plus efficacement qu'il n'aurait été le cas sans l'objectif de ligne.

Malheureusement, lorsque la stratégie d'objectif en ligne tourne mal, cela peut être un désastre de performance (voir le post de Bart Duncan). Cela peut se produire, par exemple, lorsque l'optimiseur dispose d'informations incomplètes, rencontre une distribution de données défavorable ou fait une hypothèse non sûre. Dans tous les cas, la cause des performances médiocres est presque toujours due au fait que beaucoup plus de lignes doivent être traitées au moment de l'exécution que prévu par l'optimiseur.

Il peut être très utile d'identifier les zones du plan d'exécution affectées par un objectif de ligne, car cela nous aide à comprendre pourquoi l'optimiseur a fait les choix qu'il a faits. Ceci est particulièrement important lorsque la logique d'objectif de ligne produit un résultat négatif. Sans comprendre le rôle joué par l'objectif de ligne, il peut sembler que l'optimiseur a simplement sous-estimé le nombre de lignes, amenant les gens à chercher aux mauvais endroits (par exemple, les statistiques) pour une cause profonde.

Définir des objectifs de ligne

Il est beaucoup plus facile de rechercher des effets d'objectif de ligne si l'on sait quelles sortes de choses pourraient entraîner la définition d'un objectif de ligne en premier lieu. La documentation officielle parle souvent d'objectifs de ligne associés aux mots-clés TOP , FAST , IN , et EXISTS . Cela peut laisser le lecteur avec une compréhension incomplète ou trompeuse, il vaut donc la peine de prendre un moment pour clarifier certains aspects.

Je tiens à souligner dès le départ que l'utilisation de mots-clés T-SQL spécifiques dans une requête ne garantit pas qu'un objectif de ligne sera défini . La documentation officielle mentionne certains mots-clés pour aider les gens à identifier les scénarios courants où les objectifs de ligne peuvent être introduit, sans entrer dans trop de détails techniques.

Un deuxième point général à garder à l'esprit est qu' un objectif de ligne n'est défini que lorsque l'objectif serait inférieur à l'estimation régulière . Après tout, il ne sert à rien de générer un fragment de plan optimisé pour 100 lignes si l'ensemble ne devrait produire que 50 lignes de toute façon. Pour être plus clair, ce point s'applique toujours à toutes les façons dont un objectif de ligne peut être défini. Si vous attendez un objectif de ligne, mais que vous n'en voyez pas, il s'agit probablement d'une cause.

Enfin, pour le préambule, notez que les objectifs de ligne sont une chose d'optimisation basée sur les coûts ; un objectif de ligne affecte les choix de l'optimiseur, donc s'il n'y a pas de choix à faire (c'est-à-dire un plan trivial), il n'y a pas d'effet d'objectif de ligne.

Examinons maintenant les éléments qui peuvent définir un objectif de ligne :

RAPIDE et TOP

Utiliser le FAST l'indicateur de requête est un moyen fiable de définir un objectif de ligne à la racine du plan d'exécution (sous réserve des exceptions générales indiquées ci-dessus). A SET ROWCOUNT n définit également un objectif de ligne de niveau supérieur similaire (lorsque n n'est pas nul bien sûr) pour les déclarations auxquelles il s'applique.

Écrire un TOP clause dans une requête aboutit également très souvent à un objectif de ligne. Tant que le plan d'exécution terminé comporte un opérateur Top physique, il est probable qu'au moins une partie du plan sous l'opérateur Top ait été affectée par un objectif de ligne (là encore, les conditions générales s'appliquent).

Notez que les principaux opérateurs introduits par l'optimiseur de requêtes (sans TOP spécifié par la requête clause) peut également définir un objectif de ligne. Ceci est important, car cela peut se produire de toutes sortes de façons, par exemple lors du filtrage sur un simple numéro de ligne, comme indiqué dans la requête AdventureWorks suivante :

SELECT
    THN.RowNum,
    THN.TransactionID 
FROM 
(
    SELECT 
        TH.TransactionID, 
        RowNum = 
            ROW_NUMBER() OVER (
                ORDER BY TH.TransactionID ASC)
    FROM Production.TransactionHistory AS TH
    WHERE
        TH.ProductID = 400
) AS THN
WHERE
    THN.RowNum >= 10
    AND THN.RowNum < 20
ORDER BY
    THN.RowNum ASC;

Le plan d'exécution de cette requête inclut un opérateur Top ajouté par l'optimiseur (pour limiter le nombre de lignes traitées à 20) :