2009-02-06 7 views
14

Ok, así que me doy cuenta de que esta es una pregunta bastante vaga, pero tengan paciencia conmigo.¿Por qué una combinación de SQL elige un plan de consulta subóptimo?

He experimentado este problema en numerosas ocasiones con consultas diferentes y no relacionadas. La consulta siguiente toma muchos minutos para ejecutar:

SELECT <Fields> 
FROM <Multiple Tables Joined> 
    LEFT JOIN (SELECT <Fields> FROM <Multiple Tables Joined>) ON <Condition> 

Sin embargo, con sólo añadir la sugerencia de combinación que consultar los ejecuta en cuestión de segundos:

SELECT <Fields> 
FROM <Multiple Tables Joined> 
    LEFT HASH JOIN (SELECT <Fields> FROM <Multiple Tables Joined>) ON <Condition> 

Lo más curioso es el tipo de unión se especifica en el La sugerencia no es realmente lo que mejora el rendimiento. Parece ser porque la sugerencia hace que el optimizador ejecute la consulta secundaria aisladamente y luego se una. Veo la misma mejora de rendimiento si creo una función de valor de tabla (no una en línea) para la subconsulta. p.ej.

SELECT <Fields> 
FROM <Multiple Tables Joined> 
    LEFT JOIN dbo.MySubQueryFunction() ON <Condition> 

¿Alguien tiene alguna idea de por qué el optimizador es tan tonto en este caso?

+0

¿Qué versión de SQL Server estás usando? – Austin

+0

He tenido el problema tanto en 2005 como en 2008 –

Respuesta

13

Si cualquiera de esas tablas son variables de tabla, el optimizador usa una mala estimación de 0 filas y generalmente elige el bucle anidado como la técnica de unión.

Hace esto debido a la falta de estadísticas en las tablas involucradas.

+0

No estoy usando variables de tabla pero a menudo hay vistas en la consulta secundaria. Sin embargo, tu razonamiento tiene sentido para mí. –

+1

Cuando elimino la sugerencia de combinación, el plan de consulta cambia sustancialmente y presenta bucles anidados. No puedo encontrar dónde está haciendo la mala estimación de filas, pero no puedo pasar más tiempo mirando. –

7

Optimizer es un algoritmo. No es tonto o inteligente, funciona de la manera en que está programado.

Hash join implica construir una tabla hash en una fuente de fila más pequeña, es por eso que la consulta interna se debe ejecutar primero.

En el primer caso, el optimizador podría haber elegido un nested loop. Impulsó la condición de unión en la consulta interna y ejecutó la consulta interna en cada iteración con un predicado adicional. Es posible que no encuentre un índice apropiado para este predicado, y se realizó un full table scan en cada iteración.

Es difícil decir por qué sucede esto a menos que publique su consulta exacta y cuántas filas hay en sus tablas.

Con una función de tabla, es imposible insertar una condición de unión en la consulta interna, por eso solo se ejecuta una vez.

+0

Acepto que es lo que parece estar sucediendo. Simplemente no sé por qué el optimizador elige hacer un ciclo anidado. –

+0

Es difícil de decir, necesitamos ver la consulta exacta y cuántas filas hay en las tablas. – Quassnoi

+0

He intentado reducir la consulta, pero la más pequeña que puedo obtener mientras reproduzco el problema es de 43 líneas.No quiero pasar el dolor de tratar de analizar eso sin la base de datos. –

-4

Inside SQL Server 2005: T-SQL Query responde estas y muchas otras preguntas. Uno de los mejores looks bajo la captación de datos T-SQL y el procesamiento de verbos que he visto. (No, no soy autor del libro, ni estoy afiliado a ningún autor o autores del libro, ni a Microsoft, ni a Microsoft Press. Esto es simplemente un trabajo increíble, y varios DBA han convertido esto en el pasado dos años de acuerdo.)

+0

Conozco a Itzik: probablemente sea una de las personas SQL más inteligentes del planeta. – keithwarren7

Cuestiones relacionadas