Estadísticas. ¿Son posibles los histogramas de varias columnas?

13

Estoy pensando en una situación en la que tengo dos columnas con alta densidad pero estas columnas no son independientes.

Definición

Aquí está la definición de la tabla que he creado para fines de prueba.

CREATE TABLE [dbo].[StatsTest](
    [col1] [int] NOT NULL,  --can take values 1 and 2 only
    [col2] [int] NOT NULL,  --can take integer values from 1 to 4 only
    [col3] [int] NOT NULL,  --integer. it has not relevance just to ensure that each row is different
    [col4]  AS ((10)*[col1]+[col2])  --a computed column ensuring that if two rows have different values in col1 or col2 have different values in col4 
) ON [PRIMARY]

Datos

Los datos para el experimento son los siguientes

col1    col2    col3    col4
1       1       1       11
1       2       2       12
1       2       3       12
1       3       4       13
1       3       5       13
1       3       6       13
1       4       7       14
1       4       8       14
1       4       9       14
1       4       10      14
2       1       11      21
2       1       12      21
2       1       13      21
2       1       14      21
2       2       15      22
2       2       16      22
2       2       17      22
2       3       18      23
2       3       19      23
2       4       20      24

Paso 1: filtrado por col1

SELECT * FROM StatsTest WHERE col1=1

Como se esperaba, el Optimizador de consultas adivina el número exacto de filas. Número real de filas = 10 y número estimado de filas = 10

Paso 2: filtrado por col2

SELECT * FROM StatsTest WHERE col2=1

Nuevamente tenemos una estimación perfecta.

Número real de filas = 5 y número estimado de filas = 5

Paso 3: filtrado por col1 y col2

SELECT * FROM StatsTest WHERE col1=1 AND col2=1

Aquí la estimación está lejos de estar cerca del número real de filas. Número real de filas = 1 y número estimado de filas = 3,53553

El problema es que la implicidad del analizador de consultas supone que col1 y col2 son independientes pero no lo son.

Paso 4: filtrado por col4

SELECT * FROM StatsTest WHERE col4 = 11

Puedo filtrar por col4 = 11 para obtener los mismos resultados que la consulta en el Paso 3, porque col4 es una columna calculada y de acuerdo con la forma en que se ha definido col1 = 1 y col2 = 1 es equivalente a col4 = 11 Aquí, sin embargo , como se esperaba, la estimación es perfecta.

Número real de filas = 1 y número estimado de filas = 1

Conclusión / Pregunta

¿Es esta solución artificial y poco elegante la única opción disponible para lograr estimaciones precisas cuando se trata de filtrar por dos o más columnas no independientes? ¿La columna calculada y el filtro por la columna calculada son estrictamente necesarios para obtener una precisión real?

Ejemplo en sqlfiddle

JGA
fuente
¿Por qué no construir algunos índices en col1 / 2?
LowlyDBA
De hecho, lo hice pero no lo incluí aquí porque no funcionó. Para el histograma solo se considera la primera columna y la densidad solo considera el número diferente de valores y no su distribución
JGA

Respuestas:

15

¿Son posibles los histogramas de varias columnas?

No son verdaderos histogramas multidimensionales, no.

¿Es esta solución artificial y poco elegante la única opción disponible para lograr estimaciones precisas cuando se trata de filtrar por dos o más columnas no independientes?

SQL Server admite estadísticas de "varias columnas" , pero solo capturan información de densidad promedio (correlación) además de un histograma en la primera columna nombrada. Solo son útiles para las comparaciones de igualdad.

La información de densidad promedio no captura ningún detalle, por lo que obtendrá la misma selectividad para cualquier par de valores en un objeto de estadísticas de dos columnas. En algunos casos, las estadísticas de varias columnas pueden ser lo suficientemente buenas y mejores que nada. Las estadísticas de columnas múltiples se crean automáticamente en índices de columnas múltiples.

Dependiendo de la versión de SQL Server, también puede utilizar índices filtrados y estadísticas filtradas :

-- Filtered statistics example
CREATE STATISTICS stats_StatsTest_col2_col1_eq_1
ON dbo.StatsTest (col2)
WHERE col1 = 1;

CREATE STATISTICS stats_StatsTest_col2_col1_eq_2
ON dbo.StatsTest (col2)
WHERE col1 = 2;

O puede crear una vista indizada (que puede admitir índices y estadísticas propias). Las vistas indexadas son el mecanismo detrás de la DATE_CORRELATION_OPTIMIZATIONconfiguración de la base de datos , una característica poco utilizada para las correlaciones entre tablas, pero que se aplica al espíritu de la pregunta.

¿La columna calculada y el filtro por la columna calculada son estrictamente necesarios para obtener una precisión real?

No es el único método. Además de las cosas ya mencionadas, también puede especificar la definición textual exacta de la columna calculada y el optimizador generalmente la comparará con las estadísticas de la columna calculada.

También hay marcas de seguimiento que cambian las suposiciones hechas sobre las correlaciones de varias columnas. Además, el supuesto de correlación predeterminado en SQL Server 2014 (con el nuevo estimador de cardinalidad habilitado) se cambia de Independencia a Retraso exponencial (más detalles aquí y aquí ). En última instancia, esta es una suposición diferente. Será mejor en muchos casos y peor en otros.

La precisión exacta en la estimación de cardinalidad no siempre es necesaria para obtener un buen plan de ejecución. Siempre existe una compensación entre generar un plan que se pueda reutilizar para diferentes valores de parámetros y un plan que sea óptimo para una ejecución específica, pero que no se reutilice.

Paul White 9
fuente