sql-server-2008 - tablas - inner join en sql
opción del operador optimizador de consultas-bucles anidados vs combinación de hash(o combinación) (2)
Uno de mis procedimientos almacenados tardaba demasiado en ejecutarse. Echando un vistazo al plan de ejecución de consultas, pude ubicar la operación por demasiado tiempo. Era un operador físico de bucle anidado que tenía una tabla externa (65991 filas) y una tabla interna (19223 filas). En el ciclo anidado, mostró filas estimadas = 1,268,544,993 (multiplicando 65991 por 19223) como se muestra a continuación:
Leí algunos artículos sobre los operadores físicos utilizados para las uniones y me confundí un poco si el ciclo anidado o la coincidencia hash hubieran sido mejores para este caso. Por lo que pude reunir:
Hash Match: el optimizador lo utiliza cuando no hay índices útiles disponibles, una tabla es sustancialmente más pequeña que la otra, las tablas no se ordenan en las columnas de combinación. Además, la coincidencia hash podría indicar que se podría utilizar un método de combinación más eficiente (bucles anidados o unión combinada).
Pregunta: ¿Sería mejor el emparejamiento hash que los loops anidados en este escenario?
Gracias
No recomendaría tratar de "arreglar" el plan forzando los consejos en una dirección u otra. En su lugar, debe consultar sus índices, estadísticas y el código TSQL para comprender por qué tiene un spool de Tabla cargando 1.2 billones de filas desde 19000.
ABSOLUTAMENTE. Un partido de hash sería una gran mejora. Crear el hash en la tabla de filas más pequeña de 19,223 y luego explorar con la tabla de filas 65,991 más grande es una operación mucho más pequeña que el ciclo anidado que requiere 1,268,544,993 comparaciones de filas.
La única razón por la que el servidor elegiría los bucles anidados es que subestimó seriamente el número de filas involucradas. ¿Sus tablas tienen estadísticas sobre ellos? De ser así, ¿se están actualizando regularmente? Las estadísticas son las que permiten al servidor elegir buenos planes de ejecución.
Si ha abordado correctamente las estadísticas y todavía tiene un problema, podría forzarlo a usar una combinación HASH así:
SELECT *
FROM
TableA A -- The smaller table
LEFT HASH JOIN TableB B -- the larger table
Tenga en cuenta que en el momento en que haga esto también forzará la orden de unión. Esto significa que debe organizar todas sus tablas correctamente para que su orden de unión tenga sentido. En general, debería examinar el plan de ejecución que ya tiene el servidor y modificar el orden de las tablas en la consulta para que coincida. Si no está familiarizado con la forma de hacerlo, lo básico es que cada entrada "izquierda" es lo primero, y en los planes de ejecución gráfica, la entrada izquierda es la más baja . Una unión compleja que involucre muchas tablas puede tener uniones agrupadas entre paréntesis, o usar RIGHT JOIN
para lograr un plan de ejecución óptimo (intercambie las entradas izquierda y derecha, pero introduzca la tabla en el punto correcto en el orden de unión).
Por lo general, es mejor evitar el uso de sugerencias de unión y forzar el orden de unión, ¡así que haga todo lo que pueda primero! Puede examinar los índices de las tablas, la fragmentación, reducir los tamaños de columna (como usar varchar
lugar de nvarchar
donde no se requiere Unicode) o dividir la consulta en partes (primero inserte en una tabla temporal y luego únase a eso).