2011-07-21 13 views
6

me han escuchado muchas personas en los últimos años dicen que:¿Está utilizando "NO EXISTE" una mala práctica de SQL?

"unirse" a los operadores son preferibles a “NO EXISTE”

¿Por qué?

+4

@duffymo: all guesses wrong. – Quassnoi

+1

¿Por qué está cerrado? Tengo curiosidad acerca de la razón también. –

+0

@Ziayo: probablemente debido a las palabras "mucha gente". Si está redactado "son combinaciones más eficientes que' NOT EXISTS' ", esa sería una pregunta perfecta que respondería con" hechos, referencias o experiencia específica ". – Quassnoi

Respuesta

9

En MySQL, Oracle, SQL Server y PostgreSQL, NOT EXISTS es de la misma eficacia o incluso más eficiente que LEFT JOIN/IS NULL.

Si bien puede parecer que "la consulta interna debe ejecutarse para cada registro desde la consulta externa" (que parece ser malo para NOT EXISTS y aún peor para NOT IN, ya que esta última consulta ni siquiera está correlacionada), puede optimícese tan bien como todas las otras consultas están optimizadas, utilizando los métodos apropiados anti-join.

En SQL Server, en realidad, LEFT JOIN/IS NULL puede ser menos eficiente que NOT EXISTS/NOT IN en el caso de la columna de cardinalidad unindexed o baja en la tabla interna.

A menudo se escucha que MySQL es "especialmente malo en el tratamiento de subconsultas".

Esto se debe al hecho de que MySQL no es capaz de ningún otro método de unión además de los bucles anidados, lo que limita seriamente sus capacidades de optimización.

El único caso en que una consulta se beneficiaría de la reescritura subconsulta como una unión sería la siguiente:

SELECT * 
FROM big_table 
WHERE big_table_column IN 
     (
     SELECT small_table_column 
     FROM small_table 
     ) 

small_table no se consultará por completo para cada registro de big_table: a pesar de que no parece no estar correlacionados, que se correlaciona de manera implícita por el optimizador de consultas y de hecho reescrito para un EXISTS (usando index_subquery para buscar el primer tanto, si es necesario, si se indexa small_table_column)

Pero big_table siempre sería líder, lo que hace que t consulta completa en big * LOG(small) en lugar de small * LOG(big) lecturas.

Esto podría reescribirse como

SELECT DISTINCT bt.* 
FROM small_table st 
JOIN big_table bt 
ON  bt.big_table_column = st.small_table_column 

Sin embargo, esto no mejorará NOT IN (en contraposición a IN). En MySQL, NOT EXISTS y LEFT JOIN/IS NULL son casi lo mismo, ya que con los bucles anidados, la tabla de la izquierda siempre debe estar en un LEFT JOIN.

Es posible que desee leer estos artículos:

+0

¿Durante cuánto tiempo ha sido así? –

+0

@Ian: ¿qué exactamente? – Quassnoi

+0

@Qnassnoi, que la eficiencia es aproximadamente la misma –

0

Puede tener que ver con el proceso de optimización ... NO EXISTE implica una subconsulta, y los "optimizadores" generalmente no hacen justicia a las subconsultas. Por otro lado, las uniones se pueden tratar con más facilidad ...

0

Creo que este es un caso específico de MySQL. MySQL no optimiza la subconsulta en las cláusulas IN/not in/any/not exists, y en realidad realiza la subconsulta para cada fila coincidente con la consulta externa. Debido a esto en MySQL, debes usar join. Sin embargo, en PostgreSQL, puedes usar subconsulta.

+1

Optimiza todas estas cláusulas. Por favor, lea http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/ – Quassnoi

+0

@Darhazer, parece estar atrapado en MySQL versión 4. – Johan

+0

@Johan: ... que también optimizó todos estos constructos. – Quassnoi

Cuestiones relacionadas