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

Avertissements Nombre de lignes lues / Lignes réelles lues dans Plan Explorer

La nouvelle propriété « Lecture réelle des lignes » dans les plans d'exécution (qui, dans SQL Server Management Studio, s'affiche sous la forme « Nombre de lignes lues ») était un ajout bienvenu aux optimisateurs de performances. C'est comme avoir une nouvelle superpuissance, être capable de dire la signification du prédicat de recherche par rapport au prédicat résiduel dans un opérateur de recherche. J'adore cela, car cela peut être très important pour les requêtes.

Examinons deux requêtes que j'exécute sur AdventureWorks2012. Ils sont très simples - l'un répertorie les personnes appelées John S et l'autre répertorie les personnes appelées J Smith. Comme tous les bons annuaires, nous avons un index sur LastName, FirstName.

select FirstName, LastName 
  from Person.Person
  where LastName like 'S%'
  and FirstName = 'John'; 
 
select FirstName, LastName 
  from Person.Person 
  where LastName = 'Smith' 
  and FirstName like 'J%';

Au cas où vous seriez curieux, je reçois 2 rangées de la première et 14 rangées de la seconde. Je ne suis pas vraiment intéressé par les résultats, je suis intéressé par les plans d'exécution.

Voyons ce qui se passe. J'ai ouvert une ancienne copie de SQL Sentry Plan Explorer et j'ai ouvert mes plans côte à côte. Incidemment, j'avais exécuté les deux requêtes ensemble et les deux plans se trouvaient donc dans le même fichier .sqlplan. Mais je pouvais ouvrir le même fichier deux fois dans PE et les placer côte à côte dans des groupes d'onglets.

Génial. Ils se ressemblent! Je peux voir que le Seek sur la gauche produit deux lignes au lieu de quatorze - c'est évidemment la meilleure requête.

Mais avec une fenêtre plus grande, j'aurais vu plus d'informations, et c'est une chance d'avoir exécuté les deux requêtes dans le même lot.

Vous pouvez voir que la deuxième requête, qui a produit 14 lignes au lieu de 2 lignes, a été estimée à plus de 80 % du coût ! Si j'exécutais les requêtes séparément, chacune me montrerait 100%.

Comparons maintenant avec la dernière version de Plan Explorer.

Ce qui me saute aux yeux immédiatement, c'est l'avertissement. Regardons d'un peu plus près.

L'avertissement indique "L'opération a causé des E/S résiduelles. Le nombre réel de lignes lues était de 2 130, mais le nombre de lignes renvoyées était de 2. » Effectivement, plus haut, nous voyons "Lignes réelles lues" indiquant 2 130 et Lignes réelles à 2.

Waouh ! Pour trouver ces lignes, nous avons dû parcourir 2 130 lignes ?

Vous voyez, la façon dont le Seek fonctionne est de commencer par penser au Seek Predicate. C'est celui qui exploite bien l'index, et qui fait en fait que l'opération est une recherche. Sans Seek Predicate, l'opération devient un Scan. Maintenant, s'il est garanti que ce prédicat de recherche est d'au plus une ligne (comme lorsqu'il a un opérateur d'égalité sur un index unique), alors nous avons une recherche Singleton. Sinon, nous avons un balayage de plage, et cette plage peut avoir un préfixe, un début et une fin (mais pas nécessairement à la fois un début et une fin). Cela définit les lignes de la table qui nous intéressent pour la recherche.

Mais « intéressé » ne signifie pas nécessairement « revenu », car nous pourrions avoir plus de travail à faire. Ce travail est décrit dans l'autre prédicat, qui est souvent connu sous le nom de prédicat résiduel.

Maintenant, ce prédicat résiduel pourrait en fait faire la majeure partie du travail. C'est certainement ici - il filtre les choses de 2 130 lignes à seulement 2.

Le Range Scan commence dans l'index à « John S ». Nous savons que s'il y a un "John S", ce doit être la première ligne qui peut satisfaire le tout. "Ian S" ne peut pas. Nous pouvons donc effectuer une recherche dans l'index à ce stade pour lancer notre balayage de plage. Si nous regardons le plan XML, nous pouvons le voir explicitement.

Notez que nous n'avons pas de préfixe. Cela s'applique lorsque vous avez une égalité dans la première colonne de l'index. Nous avons juste StartRange et EndRange. Le début de la plage est "Supérieur ou égal" (GE) ScanType, à la valeur "S, John" (les références de colonne hors écran sont LastName, FirstName), et la fin de la plage est "Less Than" ( LT) la valeur T. Lorsque le scan atteint T, c'est terminé. Plus rien à faire. Le Seek a maintenant terminé son Range Scan. Et dans ce cas, il renvoie 2 130 lignes !

Sauf qu'il ne renvoie pas réellement 2 130 lignes, il lit simplement 2 130 lignes. Des noms comme Barry Sai et Ken Sánchez sont lus, mais seuls les noms qui satisfont la vérification suivante sont renvoyés - le prédicat résiduel qui garantit que le prénom est John.

L'entrée Actual Rows Read dans les propriétés de l'opérateur Index Seek nous montre cette valeur de 2 130. Et bien qu'il soit visible dans les versions précédentes de Plan Explorer, nous ne recevons pas d'avertissement à ce sujet. C'est relativement nouveau.

Notre deuxième requête (à la recherche de J Smith) est beaucoup plus agréable, et il y a une raison pour laquelle elle a été estimée plus de 4 fois moins chère.

Ici, nous connaissons exactement le LastName (Smith), et le Range Scan est sur le FirstName (J%).

C'est là qu'intervient le préfixe.

Nous voyons que notre préfixe est un opérateur d'égalité (=, ScanType=”EQ”), et que LastName doit être Smith. Nous n'avons même pas encore pris en compte le début ou la fin de la plage, mais le préfixe nous indique que la plage est incluse dans la partie de l'index où LastName est Smith. Nous pouvons maintenant trouver les lignes>=J et

Il y a toujours un prédicat résiduel ici, mais c'est seulement pour s'assurer que "LIKE J%" est réellement testé. Bien qu'il nous semble intuitif que "LIKE J%" soit exactement équivalent à ">=J et

Avant le Service Pack 3 de SQL Server 2012, nous n'avions pas cette propriété, et pour avoir une idée de la différence entre la lecture réelle des lignes et les lignes réelles, nous devions utiliser l'indicateur de trace 9130. Voici ces deux plans avec ce TF activé :

Vous pouvez voir qu'il n'y a pas d'avertissement cette fois, car l'opérateur Seek renvoie les 2130 lignes. Je pense que si vous utilisez une version de SQL Server qui prend en charge cette lecture réelle des lignes, vous devez cesser d'utiliser l'indicateur de trace 9130 dans vos enquêtes et commencer à consulter les avertissements dans Plan Explorer à la place. Mais surtout, comprenez comment vos opérateurs font leur travail, car vous pourrez alors interpréter si vous êtes satisfait du plan ou si vous devez agir.

Dans un autre article, je vais vous montrer une situation dans laquelle vous préférerez peut-être que la lecture des lignes réelles soit supérieure à celle des lignes réelles.

@rob_farley