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.
Paso 2: filtrado por col2
SELECT * FROM StatsTest WHERE col2=1
Nuevamente tenemos una estimación perfecta.
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.
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.
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
Respuestas:
No son verdaderos histogramas multidimensionales, no.
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 :
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_OPTIMIZATION
configuració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.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.
fuente