¿Por qué el operador de concatenación estima menos filas que sus entradas?


20

En el siguiente fragmento de plan de consulta, parece obvio que la estimación de fila para el Concatenationoperador debería ser ~4.3 billion rows, o la suma de las estimaciones de fila para sus dos entradas.

Sin embargo, ~238 million rowsse produce una estimación de , lo que conduce a una estrategia Sort/ Stream Aggregateestrategia subóptima que derrama cientos de GB de datos a tempdb. Una estimación lógicamente consistente en este caso habría producido un Hash Aggregate, eliminado el derrame y mejorado dramáticamente el rendimiento de la consulta.

¿Es esto un error en SQL Server 2014? ¿Existen circunstancias válidas en las que una estimación inferior a las entradas podría ser razonable? ¿Qué soluciones alternativas podrían estar disponibles?

ingrese la descripción de la imagen aquí

Aquí está el plan de consulta completo (anónimo). No tengo acceso de administrador del sistema a este servidor para proporcionar resultados desde QUERYTRACEON 2363o indicadores de rastreo similares, pero es posible que pueda obtener estos resultados de un administrador si fueran útiles.

La base de datos está en el nivel de compatibilidad 120 y, por lo tanto, utiliza el nuevo Estimador de cardinalidad de SQL Server 2014.

Las estadísticas se actualizan manualmente cada vez que se cargan datos. Dado el volumen de datos, actualmente estamos utilizando la frecuencia de muestreo predeterminada. Es posible que una tasa de muestreo más alta (o FULLSCAN) pueda tener un impacto.

Respuestas:


21

Para citar a Campbell Fraser en este artículo de Connect :

Estas "inconsistencias de cardinalidad" pueden surgir en una serie de situaciones, incluso cuando se usa concat. Pueden surgir porque la estimación de un subárbol particular en el plan final puede haberse realizado en un subárbol de estructura diferente pero lógicamente equivalente. Debido a la naturaleza estadística de la estimación de cardinalidad, no se garantiza que la estimación en árboles diferentes pero lógicamente equivalentes obtenga la misma estimación. Por lo tanto, en general, no se proporcionan garantías de la consistencia esperada.

Para ampliar esto un poco: la forma en que me gusta explicarlo es decir que la estimación de cardinalidad inicial (realizada antes de que comience la optimización basada en el costo) produce estimaciones de cardinalidad más "consistentes", ya que se procesa todo el árbol inicial, con cada posterior estimación que depende directamente de la anterior.

Durante la optimización basada en el costo, se pueden explorar y reemplazar partes del árbol del plan (uno o más operadores) con alternativas, cada una de las cuales puede requerir una nueva estimación de cardinalidad. No hay una forma general de decir qué estimación será generalmente mejor que otra, por lo que es muy posible terminar con un plan final que parece "inconsistente". Esto es simplemente el resultado de unir "pedazos de planos" para formar el arreglo final.

Dicho todo esto, hubo algunos cambios detallados en el nuevo estimador de cardinalidad (CE) introducido en SQL Server 2014 que hace que esto sea algo menos común que en el caso del CE original.

Además de actualizar a la última actualización acumulativa y verificar que las correcciones del optimizador con 4199 estén activadas, sus opciones principales son probar las estadísticas / cambios de índice (anotando las advertencias de índices faltantes) y actualizaciones, o expresar la consulta de manera diferente. El objetivo es adquirir un plan que muestre el comportamiento que necesita. Esto puede congelarse con una guía de plan, por ejemplo.

El plan anónimo hace que sea difícil evaluar los detalles, pero también miraría cuidadosamente los mapas de bits para ver si son de la variedad 'optimizada' (Opt_Bitmap) o posterior a la optimización (Bitmap). También sospecho de los filtros.

Sin embargo, si los recuentos de filas son precisos, parece una consulta que podría beneficiarse del almacén de columnas. Aparte de los beneficios habituales, es posible que pueda aprovechar la concesión de memoria dinámica para los operadores de modo por lotes ( puede ser necesario el indicador de seguimiento 9389 ).


7

Construir un banco de pruebas bastante simple en SQL Server 2012 (11.0.6020) me permite recrear un plan con dos consultas coincidentes de hash que se concatenan a través de a UNION ALL. Mi banco de pruebas no muestra la estimación incorrecta que ve. Quizás este sea un problema de SQL Server 2014 CE.

Obtengo una estimación de 133.785 filas para una consulta que en realidad devuelve 280 filas, sin embargo, eso es de esperar ya que veremos más abajo:

IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
    Union1_ID INT NOT NULL
        CONSTRAINT PK_Union1
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , Union1_Text VARCHAR(255) NOT NULL
    , Union1_ObjectID INT NOT NULL
);

IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
    Union2_ID INT NOT NULL
        CONSTRAINT PK_Union2
        PRIMARY KEY CLUSTERED
        IDENTITY(2,2)
    , Union2_Text VARCHAR(255) NOT NULL
    , Union2_ObjectID INT NOT NULL
);

INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;

INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO

SELECT *
FROM dbo.Union1 u1
    INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
    INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;

Creo que la razón se debe a la falta de estadísticas para las dos uniones resultantes que están unidas. SQL Server necesita hacer conjeturas informadas en la mayoría de los casos en torno a la selectividad de las columnas ante la falta de estadísticas.

Joe Sack tiene una lectura interesante sobre eso aquí .

Por un lado UNION ALL, es seguro decir que veremos exactamente el número total de filas devueltas por cada componente de la unión, sin embargo, dado que SQL Server está usando estimaciones de filas para los dos componentes de la UNION ALL, vemos que agrega las filas totales estimadas de ambos consultas para llegar a la estimación del operador de concatenación.

En mi ejemplo anterior, el número estimado de filas para cada porción de la UNION ALLes 66.8927, que cuando se suma es 133.785, que vemos para el número estimado de filas para el operador de concatenación.

El plan de ejecución real para la consulta de unión anterior se ve así:

ingrese la descripción de la imagen aquí

Puede ver el número "estimado" frente al número "real" de filas. En mi caso, agregar el número "estimado" de filas devueltas por los dos operadores de coincidencia hash es exactamente igual a la cantidad mostrada por el operador de concatenación.

Intentaría obtener resultados del seguimiento 2363, etc., como se recomienda en la publicación de Paul White que muestra en su pregunta. Alternativamente, puede intentar usar OPTION (QUERYTRACEON 9481)en la consulta para volver a la versión 70 CE para ver si eso "soluciona" el problema.


1
Gracias. Definitivamente he visto que "la razón se debe a la falta de estadísticas para las dos uniones resultantes que están unidas" tienen un gran impacto en las uniones o agregaciones posteriores (que ocurren después de la UNIÓN). SQL 2014 en realidad maneja esto mejor que SQL 2012 en mi experiencia. Aquí hay un script de prueba simple que he usado en el pasado, por ejemplo: gist.github.com/anonymous/1497112d8b25ab8fb782a04569959c68 Sin embargo, no creo que un operador de Concatenación necesite el mismo tipo de información sobre la distribución de valores que una unión podria necesitar.
Geoff Patterson

Estoy de acuerdo con usted en que la concatenación no debería necesitar estadísticas para funcionar con precisión. Simplemente debería poder agregar de manera confiable las estimaciones de las filas entrantes para tener una idea clara del número de filas que generará. Como @PaulWhite muestra en su respuesta, sorprendentemente no siempre es así. Para mí, la conclusión aquí es que puede parecer simple, pero en realidad puede no serlo. Estoy realmente contento de que hayas hecho la pregunta de la manera en que lo hiciste, solo desearía que no tuvieras que anonimizar el plan; hubiera sido interesante ver la consulta real.
Max Vernon
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.