Estimación de cardinalidad fuera del histograma


14

Preparar

Tengo problemas para entender una estimación de cardinalidad. Aquí está mi configuración de prueba:

  • la versión 2010 de la base de datos Stack Overflow
  • SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
  • El nuevo CE (nivel de compatibilidad 140)

Tengo este proceso:

USE StackOverflow2010;
GO

CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
    @CommentCount int
AS
BEGIN
    SELECT * 
    FROM dbo.Posts p
    WHERE 
        p.CommentCount = @CommentCount
    OPTION (RECOMPILE); 
END;
GO

No hay índices o estadísticas no agrupados en la dbo.Poststabla (hay un índice agrupado activado Id).

Al solicitar un plan estimado para esto, las "filas estimadas" que salen dbo.Postsson 1,934.99:

EXEC #sp_PostsByCommentCount @CommentCount = 51;

El siguiente objeto de estadísticas se creó automáticamente cuando solicité el plan estimado:

DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);

captura de pantalla de salida de estadísticas en SSMS

Los aspectos más destacados de eso son:

  • Las estadísticas tienen una tasa de muestreo bastante baja de 1.81% (67,796 / 3,744,192)
  • Solo se usaron 31 pasos de histograma
  • El valor "Toda la densidad" es 0.03030303(se muestrearon 33 valores distintos)
  • El último RANGE_HI_KEYen el histograma es 50, con EQ_ROWS1

Pregunta

Pasar cualquier valor superior a 50 (hasta 2.147.483.647 inclusive) da como resultado la estimación de la fila de 1,934.99. ¿Qué cálculo o valor se utiliza para producir esta estimación? El estimador de cardinalidad heredado produce una estimación de 1 fila, por cierto.

Lo que he probado

Aquí hay algunas teorías que tenía, cosas que probé o fragmentos adicionales de información que pude desenterrar mientras investigaba esto.

Vector de densidad

Inicialmente pensé que sería el vector de densidad, igual que si lo hubiera usado OPTION (OPTIMIZE FOR UNKNOWN). Pero el vector de densidad para este objeto de estadísticas es 3,744,192 * 0.03030303 = 113,460, así que eso no es todo.

Eventos extendidos

Intenté ejecutar una sesión de evento extendido que recopilara el query_optimizer_estimate_cardinalityevento (que aprendí de la publicación de blog de Paul White, Estimación de la cardinalidad: combinación de estadísticas de densidad ), y obtuve este tipo de datos interesantes:

<CalculatorList>
  <FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000" 
                    CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />

  <FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001" 
                    TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true" 
                    StatId="4" />
</CalculatorList>

Entonces parece que CSelCalcAscendingKeyFilterse utilizó la calculadora (la otra dice que falló, lo que sea que eso signifique). Esta columna no es una clave, ni única, ni necesariamente ascendente, sino lo que sea.

Hacer algunas búsquedas en Google de ese término me llevó a algunas publicaciones de blog:

Estas publicaciones indican que el nuevo CE basa estas estimaciones fuera del histograma en una combinación del vector de densidad y el contador de modificación de la estadística. Desafortunadamente, ya he descartado el vector de densidad (¡creo!), Y el contador de modificación es cero (de sys.dm_db_stats_propertiestodos modos).

Banderas de seguimiento

Forrest sugirió que active TF 2363 para obtener más información sobre el proceso de estimación. Creo que lo más relevante de esa salida es esto:

Plan for computation:

  CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)

Selectivity: 0.000516798

Este es un gran avance (¡gracias, Forrest!): Ese 0.000516798número (que parece haberse redondeado inútilmente en el Selectivity="0.001"atributo XE anterior) multiplicado por el número de filas en la tabla es la estimación que he estado buscando (1,934.99).

Probablemente me falta algo obvio, pero no he podido realizar ingeniería inversa sobre cómo se produce ese valor de selectividad dentro de la CSelCalcAscendingKeyFiltercalculadora.

Respuestas:


13

Según mis pruebas, la estimación de cardinalidad fuera de los límites es simplemente la raíz cuadrada del recuento de filas, limitada a continuación por el número de filas agregadas desde la última actualización de estadísticas, y limitada por las filas promedio por valor.

En su caso, 1,934.99 = SQRT (3744192)

Prueba de configuración a continuación:

--setup
USE TestDB
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS OFF
GO

DROP TABLE IF EXISTS dbo.Hist

CREATE TABLE dbo.Hist (
ID int identity primary key,
Num int
)

INSERT dbo.Hist
SELECT TOP 300
(ROW_NUMBER() OVER(ORDER BY(SELECT 1/0)))%3
FROM master..spt_values a
CROSS JOIN master..spt_values b
--Get estimated plan
--don't forget to run right after setup to auto-create stats
SELECT *
FROM dbo.Hist
WHERE Num = 1000
--gradually add rows, then rerun estimate above
INSERT dbo.Hist
SELECT TOP 100
-1
FROM master..spt_values a
--I sure hope you weren't testing this in prod (cleanup)
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS ON
GO

Sorprendentemente, se generaron estimaciones de filas incluso a partir de este enfoque: 20 en 400 filas en total, 30 en 900, 40 en 1600, etc.

Sin embargo, después de 10000, la estimación de fila alcanza un máximo de 100, que es el número de filas por valor en las estadísticas existentes. Agregar solo 10 filas establecerá la estimación en 10, ya que sqrt (300)> 10.

Por lo tanto, las estimaciones podrían expresarse utilizando esta fórmula:

Estimate = MIN(SQRT(AC), MIN(AR, MC))

Tenga en cuenta que si se muestrean estadísticas, no se considera MC. Entonces la fórmula se convierte en:

Estimate = MIN(SQRT(AC), AR))

Dónde

  • MC es el "recuento de modificaciones" (número de modificaciones desde que se crearon las estadísticas)
  • AC es la "cardinalidad ajustada" (# de filas de las estadísticas más MC),
  • AR es el promedio de filas por valor (# de filas de las estadísticas divididas por valores distintos en la columna)

Las fórmulas para estas estimaciones y otros detalles sobre la calculadora se pueden encontrar en esta publicación de blog: Análisis de estimaciones de la calculadora CSelCalcAscendingKeyFilter

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.