Différences de lignes estimées et réelles (réelles bien inférieures à celles estimées) - trier

8

J'exécute une requête qui traite certains nœuds d'un document XML. Mon coût estimé de sous-arbre est de plusieurs millions et il semble que tout cela provienne d'une opération de tri que le serveur SQL exécute sur certaines données que j'extrais des colonnes xml via XPath. L'opération de tri a un nombre estimé de lignes à environ 19 millions, tandis que le nombre réel de lignes est d'environ 800. La requête elle-même fonctionne assez bien (1 à 2 secondes), mais l'écart me pose des questions sur les performances de la requête et pourquoi cela la différence est si grande?

Peter Smith
la source
2
Cela est peut-être dû à des statistiques obsolètes, mais vraiment impossible à dire sans plus d'informations (y compris la structure / index des tables, la requête et un plan d'exécution réel - non estimé -).
Aaron Bertrand
1
D'après mon expérience, les plans de requête qui impliquent la destruction de XML ont toujours des estimations de coûts grossièrement gonflées. Par exemple, au point que si la requête fonctionne bien en termes de temps d'exécution, j'ignore simplement les chiffres de l'estimation des coûts. Je ne sais pas pourquoi cela fait cela, mais cela peut avoir quelque chose à voir avec le fait de ne pas savoir combien de XML va être utilisé comme entrée. Si votre objectif est d'améliorer les performances de la requête, cependant, j'ai trouvé un moyen de le faire: utiliser des collections de schémas XML, comme je l'ai expliqué ici .
Jon Seigel

Réponses:

9

Aucune statistique n'est générée sur les colonnes XML. Les estimations sont devinées sur la base des expressions utilisées lors de l'interrogation du XML.

En utilisant ce tableau:

create table T(XMLCol xml not null)
insert into T values('<root><item value = "1" /></root>')

Et cette requête XML assez simple:

select X.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root/item') as X(N)

Vous donnera une ligne retournée, mais le nombre estimé de lignes retournées est de 200. Ce sera 200, quel que soit le XML ou la quantité de XML que vous remplissez dans la colonne XML pour cette ligne.

Il s'agit du plan de requête avec le nombre de lignes estimé affiché.

entrez la description de l'image ici

Un moyen d'améliorer, ou du moins de modifier, les estimations est de donner à l'optimiseur de requête plus d'informations sur le XML. Dans ce cas, parce que je sais que c'est rootvraiment un nœud racine dans le XML, je peux réécrire la requête comme ceci.

select X2.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root[1]') as X1(N)
  cross apply X1.N.nodes('item') X2(N)

Cela me donnera une estimation de 5 lignes retournées.

entrez la description de l'image ici

La réécriture de la requête n'accélérera probablement pas le déchiquetage du XML mais si les estimations sont meilleures, il est probable que l'optimiseur de requête puisse prendre des décisions plus intelligentes pour le reste de la requête.

Je n'ai trouvé aucune documentation sur les règles applicables au budget autre qu'une présentation de Michael Rys où il dit:

L'estimation de cardinalité de base est toujours de 10 000 lignes!
Certains ajustements basés sur des filtres de chemin poussés

Mikael Eriksson
la source