¿Por qué SQL Server no realiza histogramas de estadísticas de columna compuesta?

10

SQL Server tiene una cosa llamada "estadísticas de columnas múltiples", pero no es lo que uno piensa que significaría.

Echemos un vistazo a la siguiente tabla de muestra:

CREATE TABLE BadStatistics 
(
    IsArchived BIT NOT NULL,
    Id INT NOT NULL IDENTITY PRIMARY KEY,
    Mystery VARCHAR(200) NOT NULL
);

CREATE NONCLUSTERED INDEX BadIndex 
    ON BadStatistics (IsArchived, Mystery);

Con eso, se están creando dos estadísticas en los dos índices que tenemos:

Estadísticas para BadIndex:

+--------------+----------------+-------------------------+
| All density  | Average Length | Columns                 |
+--------------+----------------+-------------------------+
| 0.5          | 1              | IsArchived              |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 37             | IsArchived, Mystery     |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 41             | IsArchived, Mystery, Id |
+--------------+----------------+-------------------------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 0            | 0          | 24398   | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 216602  | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

Estadísticas para el índice agrupado:

+--------------+----------------+---------+
| All density  | Average Length | Columns |
+--------------+----------------+---------+
| 4.149378E-06 | 4              | Id      |
+--------------+----------------+---------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 240999       | 240997     | 1       | 240997              | 1              |
+--------------+------------+---------+---------------------+----------------+
| 241000       | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

(He rellenado la tabla con datos de muestra aleatorios donde aproximadamente una décima parte de las filas no están archivadas. Luego ejecuté una actualización de estadísticas de exploración completa).

¿Por qué el histograma de las estadísticas de dos columnas solo usa una columna? Sé que muchas personas han escrito sobre el que se hace , pero ¿cuál es la razón? En este caso, hace que todo el histograma sea mucho menos útil, porque la primera columna solo tiene dos valores. ¿Por qué las estadísticas se restringirían arbitrariamente así?

Tenga en cuenta que esta pregunta no se refiere a histogramas multidimensionales, que son una bestia completamente diferente. Se trata de histogramas unidimensionales, siendo la dimensión única las tuplas que contienen las respectivas columnas múltiples.

John
fuente

Respuestas:

8

Antecedentes

El modelo actual de SQL Server solo usa histogramas de una columna e información de densidad de varias columnas. Los histogramas de una sola columna se utilizan para estimar la selectividad para predicados adecuados, por ejemplo, a = 1o b > 50. Una consulta con múltiples predicados simplemente combina las selectividades individuales (con supuestos) para producir una selectividad general estimada.

Para ver un ejemplo, vea mi artículo Estimación de cardinalidad: combinación de estadísticas de densidad

La densidad de varias columnas informa más al modelo al proporcionar información de correlación débil para predicados de igualdad múltiple y cardinalidades de agrupación para agregaciones.

Las estadísticas asociadas con los índices son un complemento oportunista para ese modelo: el motor también podría recopilar estadísticas (normalmente exploración completa) mientras está creando un índice. SQL Server construye automáticamente un histograma de columna inicial e información de densidad para las otras claves.

Los histogramas para columnas no iniciales en un índice pueden ser construidos a pedido automáticamente por el procesador de consultas, o de antemano utilizando sp_createstatsla @indexonlyopción (entre otros).

Histogramas de columnas múltiples

Las suposiciones hechas al combinar estadísticas de columna única (como arriba) pueden o no modelar la realidad de los datos lo suficientemente bien. En muchos casos, las opciones disponibles (retroceso exponencial, independencia, selectividad mínima) producen una estimación "suficientemente buena".

También hemos filtrado las estadísticas (e índices) como una solución natural a los índices de columnas iniciales de baja cardinalidad, como en el ejemplo de la pregunta. Llevarlos al extremo lógico nos lleva más cerca de las estadísticas multidimensionales de las que no se trata la pregunta.

Cuando las opciones de modelado disponibles no pueden proporcionar una estimación adecuada, un histograma estadístico de varias columnas podría dar una mejor estimación de selectividad para predicados de índice adecuados, en algunos casos. Existen algunas dificultades para combinar diferentes tipos de datos en diferentes columnas, pero nada insuperable.

También necesitaríamos un histograma para cada nivel de las teclas de índice (para obtener los mejores resultados); entonces para un índice en (a, b, c)eso significaría histogramas en (a, b)y (a, b, c)además del histograma de columna única actual en (a)solo.

El mecanismo utilizado para detectar estadísticas obsoletas también debería modificarse para mantener los histogramas de columnas múltiples afectados. Es probable que estos histogramas terminen siendo reconstruidos con más frecuencia que las estadísticas de una sola columna, simplemente porque las modificaciones a más columnas los afectan.

Todo esto agrega tamaño, complejidad y gastos generales de mantenimiento.

Las estadísticas de varias columnas se pueden simular (hasta cierto punto) utilizando una estadística creada en una columna calculada cuidadosamente construida que hace referencia a varias columnas. La consulta necesitaría incluir un predicado en la columna calculada (o una coincidencia textual exacta para la fórmula subyacente) para aprovechar esa estadística. Probablemente solo haya situaciones muy limitadas en las que este enfoque sea práctico. Sin embargo, tiene algunos de los mismos problemas de implementación que los histogramas automáticos de varias columnas.

En última instancia, las únicas personas que podrían decir con certeza por qué SQL Server no admite estadísticas de varias columnas serían los propios diseñadores. Si cree que puede presentar un argumento sólido para una mejora del producto en esta área con una amplia aplicabilidad, puede sugerirlo en Connect o a través de su canal de soporte normal.

Nota

En este caso, hace que todo el histograma sea mucho menos útil, porque la primera columna solo tiene dos valores

El histograma aún proporciona información útil sobre la distribución de valores en la columna inicial: cuando se crearon las estadísticas, había 24.398 filas donde IsArchivedera falso y 216.602 filas donde era verdadero .

Además, el objeto de estadísticas nos dice que hay (1 / 0.5) = 2 valores distintos para IsArchived, (1 / 4.149378E-06) ~ = 241000 valores distintos para (IsArchived, Mystery)con un tamaño de fila promedio de 37 bytes, y hay la misma frecuencia para (IsArchived, Mystery, Id)con 4 bytes adicionales por fila.

Esa es toda buena información de propósito general, que se puede combinar con información estadística sobre otras columnas para producir una estimación de selectividad en consultas con múltiples predicados (como se mencionó).

Paul White 9
fuente