Soy un usuario de MySQL de la vieja escuela y siempre he preferido JOIN
la subconsulta. Pero hoy en día todos usan subconsultas, y lo odio; No se porque.
Me falta el conocimiento teórico para juzgar por mí mismo si hay alguna diferencia. ¿Es una subconsulta tan buena como a JOIN
y, por lo tanto, no hay nada de qué preocuparse?
Respuestas:
Tomado del manual de MySQL ( 13.2.10.11 Reescritura de subconsultas como uniones ):
Por lo tanto, las subconsultas pueden ser más lentas que
LEFT [OUTER] JOIN
, pero en mi opinión, su fuerza es una legibilidad ligeramente mayor.fuente
Join
ysub query
tiene una sintaxis diferente, por lo que no se puede comparar la legibilidad, ambas tienen una mayor legibilidad siempre que sea bueno en la sintaxis SQL. El rendimiento es más importante.Las subconsultas son la forma lógica correcta de resolver problemas de la forma "Obtener hechos de A, condicional a hechos de B". En tales casos, tiene más sentido lógico pegar B en una subconsulta que hacer una unión. También es más seguro, en un sentido práctico, ya que no tiene que ser cauteloso para obtener datos duplicados de A debido a múltiples partidos contra B.
En términos prácticos, sin embargo, la respuesta generalmente se reduce al rendimiento. Algunos optimizadores chupan limones cuando se les da una combinación frente a una subconsulta, y algunos chupan limones de la otra manera, y esto es específico del optimizador, específico de la versión DBMS y específico de la consulta.
Históricamente, las uniones explícitas generalmente ganan, de ahí la sabiduría establecida de que las uniones son mejores, pero los optimizadores mejoran todo el tiempo, por lo que prefiero escribir consultas primero de una manera lógicamente coherente, y luego reestructurarlas si las restricciones de rendimiento lo justifican.
fuente
select custid from cust join bought using (custid) where price > 500
. Si un cliente compró varios artículos caros, obtendrá duplicaciones. Para solucionar este problema,select custid from cust where exists (select * from bought where custid = cust.custid and price > 500)
. En suselect distinct …
lugar, podría usar , pero a menudo es más trabajo, ya sea para el optimizador o el evaluador.En la mayoría de los casos, los
JOIN
s son más rápidos que las subconsultas y es muy raro que una subconsulta sea más rápida.En
JOIN
s RDBMS puede crear un plan de ejecución que sea mejor para su consulta y pueda predecir qué datos se deben cargar para procesarlos y ahorrar tiempo, a diferencia de la subconsulta donde ejecutará todas las consultas y cargará todos sus datos para realizar el procesamiento .Lo bueno de las subconsultas es que son más legibles que
JOIN
s: es por eso que la mayoría de las personas SQL nuevas las prefieren; es el camino facil; pero cuando se trata de rendimiento, las UNIONES son mejores en la mayoría de los casos, aunque no son difíciles de leer también.fuente
select * from a where a.x = (select b.x form b where b.id = a.id)
son extremadamente pequeños en comparación con una unión. Este es un problema muy específico, pero en algunos casos te lleva de horas a minutos.Use EXPLAIN para ver cómo su base de datos ejecuta la consulta en sus datos. Hay un gran "depende" en esta respuesta ...
PostgreSQL puede reescribir una subconsulta a una combinación o una combinación a una subconsulta cuando cree que una es más rápida que la otra. Todo depende de los datos, índices, correlación, cantidad de datos, consulta, etc.
fuente
En el año 2010 me habría unido al autor de estas preguntas y habría votado fuertemente
JOIN
, pero con mucha más experiencia (especialmente en MySQL) puedo decir: Sí, las subconsultas pueden ser mejores. He leído múltiples respuestas aquí; Algunas subconsultas indicadas son más rápidas, pero carecía de una buena explicación. Espero poder brindarle una (muy) tardía respuesta:En primer lugar, permítanme decir lo más importante: existen diferentes formas de subconsultas
Y la segunda declaración importante: el tamaño importa
Si usa subconsultas, debe saber cómo el DB-Server ejecuta la subconsulta. ¡Especialmente si la subconsulta se evalúa una vez o por cada fila! Por otro lado, un servidor DB moderno puede optimizar mucho. En algunos casos, una subconsulta ayuda a optimizar una consulta, pero una versión más reciente del servidor DB puede hacer que la optimización sea obsoleta.
Subconsultas en campos de selección
Tenga en cuenta que se ejecuta una subconsulta para cada fila resultante de
foo
.Evite esto si es posible; puede ralentizar drásticamente su consulta en grandes conjuntos de datos. Sin embargo, si la subconsulta no tiene ninguna referencia
foo
, el servidor DB puede optimizarla como contenido estático y solo se puede evaluar una vez.Subconsultas en la instrucción Where
Si tiene suerte, el DB optimiza esto internamente en a
JOIN
. De lo contrario, su consulta se volverá muy, muy lenta en grandes conjuntos de datos porque ejecutará la subconsulta para cada filafoo
, no solo los resultados como en el tipo de selección.Subconsultas en la declaración de unión
Esto es interesante. Combinamos
JOIN
con una subconsulta. Y aquí obtenemos la verdadera fuerza de las subconsultas. Imagine un conjunto de datos con millones de filaswilco
pero solo unas pocas distintasme
. En lugar de unirse contra una mesa enorme, ahora tenemos una mesa temporal más pequeña para unirse. Esto puede resultar en consultas mucho más rápidas dependiendo del tamaño de la base de datos. Puede tener el mismo efecto conCREATE TEMPORARY TABLE ...
yINSERT INTO ... SELECT ...
, lo que podría proporcionar una mejor legibilidad en consultas muy complejas (pero puede bloquear conjuntos de datos en un nivel de aislamiento de lectura repetible).Subconsultas anidadas
Puede anidar subconsultas en varios niveles. Esto puede ayudar en grandes conjuntos de datos si tiene que agrupar u ordenar los resultados. Por lo general, el servidor DB crea una tabla temporal para esto, pero a veces no es necesario ordenar en toda la tabla, solo en el conjunto de resultados. Esto podría proporcionar un rendimiento mucho mejor dependiendo del tamaño de la tabla.
Conclusión
Las subconsultas no reemplazan a a
JOIN
y no debe usarlas así (aunque sea posible). En mi humilde opinión, el uso correcto de una subconsulta es el uso como un reemplazo rápido deCREATE TEMPORARY TABLE ...
. Una buena subconsulta reduce un conjunto de datos de una manera que no puede lograr en unaON
declaración de aJOIN
. Si una subconsulta tiene una de las palabras claveGROUP BY
o,DISTINCT
y preferiblemente no está situada en los campos de selección o en la instrucción where, podría mejorar mucho el rendimiento.fuente
Sub-queries in the Join-statement
: (1) generar una tabla derivada a partir de la subconsulta en sí podría tomar mucho tiempo. (2) la tabla derivada resultante no está indexada. estos dos solos podrían ralentizar significativamente el SQL.10
registros, ya que no hay índice, eso significa potencialmente consultar 9 veces más registros de datos que sin la tabla temporal cuando se UNE a otras tablas. Por cierto, tuve este problema antes con mi db (MySQL), en mi caso, usar subconsultasSELECT list
podría ser mucho más rápido.EXPLAIN
en una consulta antes de optimizar. Con el viejoset profiling=1
se podía ver fácilmente, si una tabla temporal es un cuello de botella. E incluso un índice necesita tiempo de procesamiento, B-Trees optimiza la consulta de registros, pero una tabla de 10 registros puede ser mucho más rápida que un índice para millones de registros. Pero depende de múltiples factores como los tamaños y tipos de campo.En primer lugar, para comparar los dos primeros, debe distinguir las consultas con subconsultas para:
Para la primera clase de consultas, un buen RDBMS verá uniones y subconsultas como equivalentes y producirá los mismos planes de consulta.
En estos días, incluso mysql hace eso.
Aún así, a veces no es así, pero esto no significa que las uniones siempre ganarán: tuve casos al usar subconsultas en mysql para mejorar el rendimiento. (Por ejemplo, si hay algo que impide que mysql planner calcule correctamente el costo y si el planificador no ve la variante de combinación y la variante de subconsulta como iguales, entonces las subconsultas pueden superar las uniones forzando una determinada ruta).
La conclusión es que debe probar sus consultas para las variantes de unión y subconsulta si desea asegurarse de cuál funcionará mejor.
Para la segunda clase, la comparación no tiene sentido ya que esas consultas no pueden reescribirse usando combinaciones y en estos casos las subconsultas son una forma natural de realizar las tareas requeridas y no debe discriminarlas.
fuente
Creo que lo que se ha subestimado en las respuestas citadas es la cuestión de los duplicados y los resultados problemáticos que pueden surgir de casos específicos (de uso).
(aunque Marcelo Cantos lo menciona)
Citaré el ejemplo de los cursos Lagunita de Stanford sobre SQL.
Mesa de estudiante
Aplicar tabla
(solicitudes hechas a universidades y especialidades específicas)
Tratemos de encontrar los puntajes de GPA para los estudiantes que se han postulado a la
CS
especialización (independientemente de la universidad)Usando una subconsulta:
El valor promedio para este conjunto de resultados es:
Usando una unión:
valor promedio para este conjunto de resultados:
Es obvio que el segundo intento arroja resultados engañosos en nuestro caso de uso, dado que cuenta duplicados para el cálculo del valor promedio. También es evidente que el uso de
distinct
con la declaración basada en unirse no eliminará el problema, dado que mantendrá erróneamente una de cada tres ocurrencias de la3.9
puntuación. El caso correcto es dar cuenta de DOS (2) ocurrencias del3.9
puntaje dado que en realidad tenemos DOS (2) estudiantes con ese puntaje que cumplen con nuestros criterios de consulta.Parece que en algunos casos una subconsulta es la forma más segura de hacerlo, además de cualquier problema de rendimiento.
fuente
La documentación de MSDN para SQL Server dice
así que si necesitas algo como
intenta usar join en su lugar. En otros casos, no hay diferencia.
Digo: Crear funciones para subconsultas elimina el problema del desorden y le permite implementar lógica adicional a las subconsultas. Por lo tanto, recomiendo crear funciones para subconsultas siempre que sea posible.
El desorden en el código es un gran problema y la industria ha estado trabajando para evitarlo durante décadas.
fuente
NOT EXISTS
. ANOT EXISTS
gana sobre aLEFT OUTER JOIN
por varias razones: rendimiento, seguridad ante fallas (en el caso de columnas anulables) y legibilidad. sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-joinEjecutar en una base de datos muy grande desde un viejo CMS Mambo:
0 segundos
~ 3 segundos
Una EXPLICACIÓN muestra que examinan exactamente el mismo número de filas, pero una toma 3 segundos y la otra es casi instantánea. ¿Moraleja de la historia? Si el rendimiento es importante (¿cuándo no lo es?), Pruébelo de varias maneras y vea cuál es el más rápido.
Y...
0 segundos
De nuevo, los mismos resultados, el mismo número de filas examinadas. Supongo que DISTINCT mos_content.catid tarda mucho más en darse cuenta que DISTINCT mos_categories.id.
fuente
id
y no nombrada algo asícatid
? Tratando de optimizar mis accesos db, y sus aprendizajes podrían ayudar.Según mi observación, como dos casos, si una tabla tiene menos de 100,000 registros, la unión funcionará rápidamente.
Pero en el caso de que una tabla tenga más de 100,000 registros, entonces una subconsulta es el mejor resultado.
Tengo una tabla que tiene 500,000 registros que creé debajo de la consulta y su tiempo de resultado es como
fuente
Las subconsultas generalmente se usan para devolver una sola fila como valor atómico, aunque se pueden usar para comparar valores contra varias filas con la palabra clave IN. Se permiten en casi cualquier punto significativo en una declaración SQL, incluida la lista de destino, la cláusula WHERE, etc. Una subconsulta simple podría usarse como condición de búsqueda. Por ejemplo, entre un par de tablas:
Tenga en cuenta que el uso de un operador de valor normal en los resultados de una subconsulta requiere que solo se devuelva un campo. Si está interesado en verificar la existencia de un solo valor dentro de un conjunto de otros valores, use IN:
Obviamente, esto es diferente de decir una IZQUIERDA IZQUIERDA donde solo desea unir elementos de la tabla A y B, incluso si la condición de unión no encuentra ningún registro coincidente en la tabla B, etc.
Si solo le preocupa la velocidad, tendrá que consultar con su base de datos y escribir una buena consulta y ver si hay alguna diferencia significativa en el rendimiento.
fuente
Versión de MySQL: 5.5.28-0ubuntu0.12.04.2-log
También tenía la impresión de que JOIN siempre es mejor que una subconsulta en MySQL, pero EXPLAIN es una mejor manera de hacer un juicio. Aquí hay un ejemplo donde las subconsultas funcionan mejor que JOIN.
Aquí está mi consulta con 3 subconsultas:
EXPLICAR muestra:
La misma consulta con JOIN es:
y la salida es:
Una comparación de la
rows
columna indica la diferencia y la consulta con JOIN está utilizandoUsing temporary; Using filesort
.Por supuesto, cuando ejecuto ambas consultas, la primera se realiza en 0.02 segundos, la segunda no se completa incluso después de 1 minuto, por lo que EXPLICAR explicó estas consultas correctamente.
Si no tengo el INNER JOIN en la
list_tag
tabla, es decir, si eliminodesde la primera consulta y correspondientemente:
desde la segunda consulta, EXPLAIN devuelve el mismo número de filas para ambas consultas y ambas consultas se ejecutan igualmente rápido.
fuente
Las subconsultas tienen la capacidad de calcular funciones de agregación sobre una marcha. Por ejemplo, encuentre el precio mínimo del libro y obtenga todos los libros que se venden con este precio. 1) Uso de subconsultas:
2) usando JOINs
fuente
GROUP BY
s con diferentes tablas: stackoverflow.com/questions/11415284/… Las subconsultas parecen ser estrictamente más generales. Consulte también el hombre de MySQL: dev.mysql.com/doc/refman/5.7/en/optimizing-subqueries.html | dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.htmlAlgunas personas dicen que "algunos RDBMS pueden reescribir una subconsulta a una combinación o una combinación a una subconsulta cuando cree que una es más rápida que la otra", pero esta afirmación se aplica a casos simples, seguramente no para consultas complicadas con subconsultas que realmente causan una problemas en el rendimiento
fuente
La diferencia solo se ve cuando la segunda tabla de unión tiene significativamente más datos que la tabla primaria. Tuve una experiencia como la de abajo ...
Teníamos una tabla de usuarios de cien mil entradas y sus datos de membresía (amistad) de aproximadamente trescientas mil entradas. Fue una declaración conjunta para tomar amigos y sus datos, pero con un gran retraso. Pero estaba funcionando bien donde solo había una pequeña cantidad de datos en la tabla de miembros. Una vez que lo cambiamos para usar una subconsulta, funcionó bien.
Pero mientras tanto, las consultas de combinación funcionan con otras tablas que tienen menos entradas que la tabla principal.
Entonces, creo que las declaraciones de unión y subconsulta funcionan bien y depende de los datos y la situación.
fuente
En estos días, muchos dbs pueden optimizar subconsultas y uniones. Por lo tanto, solo tiene que examinar su consulta usando explicar y ver cuál es más rápido. Si no hay mucha diferencia en el rendimiento, prefiero usar subconsultas, ya que son simples y fáciles de entender.
fuente
Solo estoy pensando en el mismo problema, pero estoy usando subconsulta en la parte FROM. Necesito conectar y consultar desde tablas grandes, la tabla "esclava" tiene 28 millones de registros, ¡pero el resultado es solo 128, tan pequeño como resultado, grandes datos! Estoy usando la función MAX () en él.
Primero estoy usando LEFT JOIN porque creo que esa es la forma correcta, mysql puede optimizar, etc. La segunda vez solo para probar, reescribo para sub-seleccionar contra JOIN.
Tiempo de ejecución de IZQUIERDA UNIR: 1.12s Tiempo de ejecución de SUB-SELECT: 0.06s
¡18 veces más rápido la subselección que la unión! Justo en el chokito adv. La subselección se ve terrible pero el resultado ...
fuente
Si desea acelerar su consulta usando join:
Para "unión / unión interna", no use la condición where en lugar de usarla en la condición "ON". P.ej:
Para "Unión izquierda / derecha", no use en la condición "ON", porque si usa la unión izquierda / derecha obtendrá todas las filas para cualquier tabla. Por lo tanto, no tiene sentido usarla en "On". Entonces, trate de usar la condición "Dónde"
fuente