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é?
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é?
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:
¿Durante cuánto tiempo ha sido así? –
@Ian: ¿qué exactamente? – Quassnoi
@Qnassnoi, que la eficiencia es aproximadamente la misma –
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 ...
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.
@duffymo: all guesses wrong. – Quassnoi
¿Por qué está cerrado? Tengo curiosidad acerca de la razón también. –
@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