Diferencias de filas estimadas vs reales (reales mucho más pequeñas que las estimadas) - ordenar

8

Estoy ejecutando una consulta que procesa algunos nodos de un documento XML. Mi costo estimado de subárbol es de millones y parece que todo proviene de una operación de clasificación que el servidor sql está realizando en algunos datos que extraigo de columnas xml a través de XPath. La operación Ordenar tiene un número estimado de filas de alrededor de 19 millones, mientras que el recuento de filas real es de aproximadamente 800. La consulta en sí se ejecuta razonablemente bien (1 a 2 segundos), pero la discrepancia me hace preguntarme sobre el rendimiento de la consulta y por qué esto la diferencia es tan grande?

Peter Smith
fuente
2
Posiblemente esto se deba a estadísticas desactualizadas, pero es realmente imposible saberlo sin más información (incluida la estructura / índices de la tabla, la consulta y un plan de ejecución real, no estimado).
Aaron Bertrand
1
Desde mi experiencia, los planes de consulta que implican la destrucción de XML siempre tienen estimaciones de costos muy inflados. Me gusta, hasta el punto de que si la consulta funciona bien en términos de tiempo de ejecución, simplemente ignoro los números estimados de costos. No tengo idea de por qué hace eso, pero puede tener algo que ver con no saber cuánto XML se utilizará como entrada. Sin embargo, si su objetivo es mejorar el rendimiento de la consulta, una forma de hacerlo es usar colecciones de esquemas XML, como escribí aquí .
Jon Seigel

Respuestas:

9

No hay estadísticas generadas en columnas XML. Las estimaciones se adivinan en función de las expresiones utilizadas al consultar el XML.

Usando esta tabla:

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

Y esta consulta XML bastante simple:

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

Le dará una fila devuelta pero las filas estimadas devueltas son 200. Será 200 independientemente de qué XML o cuánto XML ingrese en la columna XML para esa fila.

Este es el plan de consulta con el recuento de filas estimado que se muestra.

ingrese la descripción de la imagen aquí

Una forma de mejorar, o al menos cambiar, las estimaciones es proporcionar al optimizador de consultas más información sobre el XML. En este caso, porque que rootrealmente es un nodo raíz en el XML, puedo reescribir la consulta de esta manera.

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)

Eso me dará una estimación de 5 filas devueltas.

ingrese la descripción de la imagen aquí

La reescritura de la consulta probablemente no acelerará la destrucción del XML, pero si las estimaciones son mejores, es probable que el optimizador de consultas pueda tomar decisiones más inteligentes para el resto de la consulta.

No he encontrado ninguna documentación sobre cuáles son las reglas para las estimaciones que no sea una presentación de Michael Rys donde dice:

¡La estimación de cardinalidad base es siempre de 10'000 filas!
Algunos ajustes basados ​​en filtros de ruta empujados

Mikael Eriksson
fuente