¿Cómo calcula el optimizador de SQL Server el número de filas en una tabla unida?


13

Estoy ejecutando esta consulta en la base de datos AdventureWorks2012 :

SELECT 
    s.SalesOrderID,
    d.CarrierTrackingNumber,
    d.ProductID,
    d.OrderQty
FROM Sales.SalesOrderHeader s 
JOIN Sales.SalesOrderDetail d 
    ON s.SalesOrderID = d.SalesOrderID
WHERE s.CustomerID = 11077

Si miro el plan de ejecución estimado, veo lo siguiente:

ingrese la descripción de la imagen aquí

La búsqueda de índice inicial (arriba a la derecha) está utilizando el índice IX_SalesOrderHeader_CustomerID y está buscando en el literal 11077. Tiene una estimación de 2.6192 filas.

ingrese la descripción de la imagen aquí

Si lo uso DBCC SHOW_STATISTICS ('Sales.SalesOrderHeader', 'IX_SalesOrderHeader_CustomerID') WITH HISTOGRAM, muestra que el valor 11077 está entre las dos claves muestreadas 11019 y 11091.

ingrese la descripción de la imagen aquí

El número promedio de filas distintas entre 11019 y 11091 es 2.619718, o redondeado a 2.61972, que es el valor de las filas estimadas que se muestran para la búsqueda de índice.

La parte que no entiendo es el número estimado de filas para la búsqueda de índice agrupado en la tabla SalesOrderDetail.

ingrese la descripción de la imagen aquí

Si corro DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', 'PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID'):

ingrese la descripción de la imagen aquí

Entonces, la densidad de SalesOrderID (a la que me estoy uniendo) es 3.178134E-05. Eso significa que 1 / 3.178134E-05 (31465) es igual al número de valores únicos de SalesOrderID en la tabla SalesOrderDetail.

Si hay 31465 SalesOrderID únicos en SalesOrderDetail, entonces, con una distribución uniforme, el número promedio de filas por SalesOrderID es 121317 (número total de filas) dividido por 31465. El promedio es 3.85561

Entonces, si el número estimado de filas para recorrer es 2.61972, y el promedio que se devolverá en 3.85561, creo que el número estimado de filas sería 2.61972 * 3.85561 = 10.10062.

Pero el número estimado de filas es 11.4867.

Creo que mi comprensión de la segunda estimación es incorrecta y los diferentes números parecen indicar eso. ¿Qué me estoy perdiendo?

Respuestas:


20

Creo que mi comprensión de la segunda estimación es incorrecta y los diferentes números parecen indicar eso. ¿Qué me estoy perdiendo?

Al usar el estimador de cardinalidad de SQL Server 2012, la selectividad de la unión impulsa el número estimado de filas en el lado interno de la unión de bucles anidados, y no al revés.

El número 11.4867 se deriva (para mostrar en el plan de presentación) dividiendo la cardinalidad estimada calculada de la salida de unión (30.0919) por el número de iteraciones (2.61972). El resultado, usando aritmética de coma flotante de precisión simple, es 11.4867 .

Realmente es tan simple como eso. Tenga en cuenta que la selectividad de unión (lógica) es independiente de la elección del operador de unión física. Sigue siendo el mismo si la unión se realiza en última instancia utilizando un operador físico Nested Loops, Hash o Merge Join.

En SQL Server 2012 y versiones anteriores, la selectividad de unión (como un todo) se estima usando los SalesOrderIDhistogramas de cada tabla (calculados para cada paso del histograma, después de la alineación de límites de paso usando la interpolación lineal según sea necesario). El SalesOrderIDhistograma asociado con la SalesOrderHeadertabla también se ajusta para el efecto de escala del CustomerIDfiltro independiente .

Eso no quiere decir que haya algo fundamentalmente "incorrecto" con el cálculo alternativo propuesto en la pregunta; solo hace un conjunto diferente de suposiciones. Siempre habrá diferentes formas de calcular o combinar estimaciones para una secuencia dada de operaciones lógicas. No existe una garantía general de que diferentes métodos estadísticos aplicados a los mismos datos produzcan las mismas respuestas, o que un método siempre sea superior al otro. Las inconsistencias resultantes de la aplicación de diferentes métodos estadísticos pueden incluso aparecer dentro de un único plan de ejecución final, aunque rara vez se notan.

Como nota al margen, el estimador de cardinalidad de SQL Server 2014 adopta un enfoque diferente para combinar la información de histograma ajustada por filtro independiente ( "alineación aproximada" ), lo que da como resultado una estimación final diferente de 10.1006 filas para esta consulta:

Plan for computation:

  CSelCalcExpressionComparedToExpression
  (QCOL: [s].SalesOrderID x_cmpEq QCOL: [d].SalesOrderID)

Loaded histogram for column QCOL: [s].SalesOrderID from stats with id 1
Loaded histogram for column QCOL: [d].SalesOrderID from stats with id 1

Stats collection generated: 

  CStCollJoin(ID=4, **CARD=10.1006** x_jtInner)
      CStCollFilter(ID=3, CARD=2.61972)
          CStCollBaseTable(ID=1, CARD=31465 TBL: Sales.SalesOrderHeader AS TBL: s)
      CStCollBaseTable(ID=2, CARD=121317 TBL: Sales.SalesOrderDetail AS TBL: d)

Esto resulta ser el mismo resultado que el cálculo en la pregunta, aunque el razonamiento detallado es diferente (es decir, no se basa en una implementación supuesta de bucles anidados).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.