Usando la palabra clave JOIN o no

45

Las siguientes consultas SQL son las mismas:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

Y ciertamente da como resultado los mismos planes de consulta en cada DBMS que he probado.

Pero de vez en cuando, leo o escucho una opinión de que uno es definitivamente mejor que el otro. Naturalmente, estas afirmaciones nunca se justifican con una explicación.

Donde trabajo, la segunda versión parece ser favorecida por la mayoría de los otros desarrolladores, por lo que también tiendo a ese estilo para minimizar la sorpresa. Pero en mi corazón, realmente estoy pensando en el primero (ya que así es como lo aprendí originalmente).

¿Es una de estas formas objetivamente mejor que la otra? Si no, ¿cuáles serían las razones para usar una sobre la otra?

SingleNegationElimination
fuente
1
¿Por qué no perfilarlo y dejar que el resto sepamos el resultado? En términos generales, el rendimiento supera con creces la preferencia de estilo.
Demian Brecht
3
"da como resultado los mismos planes de consulta en todos los DBMS que he probado" Si esto pudiera tener una respuesta en términos de rendimiento, lo habría preguntado en stackoverflow.com. Por desgracia, son la misma consulta.
SingleNegationElimination
Ah .. Perdí eso :)
Demian Brecht
2
"Subjetivo" no significa "cuál es su opinión". He editado este de tipo de cumplir los criterios establecidos en el FAQ .
Aaronaught
También tiendo a ese estilo para minimizar la sorpresa , creo que acabas de responder tu propia pregunta. Las sorpresas son malas.
Pieter B

Respuestas:

60

Encuentro que la segunda forma es mejor. Puede ser porque así lo aprendí, lo admito, pero tengo una razón concreta: la separación de las preocupaciones. Poner los campos que está utilizando para unir las tablas en la cláusula where puede generar dificultades para comprender las consultas.

Por ejemplo, tome la siguiente consulta:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

La consulta anterior tiene condiciones de unión de tabla y condiciones de lógica de negocios reales, todas combinadas en un solo espacio. Con una consulta grande, esto puede ser muy difícil de entender.

Sin embargo, ahora tome este código:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

En este caso, todo lo que tenga que ver con las tablas o cómo se relacionan está aislado de la cláusula from, mientras que la lógica comercial real para la restricción de consultas está en la cláusula where. Creo que eso es mucho más comprensible, particularmente para consultas más grandes.

Dustin Wilhelmi
fuente
Esta es la única forma sensata de hacerlo, especialmente una vez que pasa dos tablas, o necesita una combinación de combinaciones izquierda, derecha y completa.
aglassman
55
+1 Para las uniones de "separación de preocupaciones", reúna los datos, donde las cláusulas dictan los subconjuntos de datos que le interesan.
39

La sintaxis de unión reemplazó a la antigua sintaxis de coma en 1992. Actualmente no hay ninguna razón para escribir código con la sintaxis de coma. No gana nada y está sujeto a algunos problemas que simplemente no tiene con la sintaxis explícita.

En primer lugar, a medida que obtiene consultas más complicadas, es muy fácil hacer una unión cruzada accidental al perder una condición where. Esto es algo que la sintaxis de unión explícita puede evitar que ocurra, ya que obtendrá un error de sintaxis.

Si tiene la intención de una unión cruzada, la sintaxis de unión explícita lo dejará claro, mientras que en la sintaxis implícita alguien que realiza mantenimiento puede asumir que olvidó agregar la cláusula where.

Luego está el problema de las uniones izquierda y derecha que son problemáticas en al menos algunos dbs que usan la sintaxis implícita. Están en desuso en SQL Server y, de hecho, no devuelven resultados correctos incluso en las versiones anteriores. Ninguna consulta que necesite una combinación externa debe contener la sintaxis implícita en SQL Server.

Además, he visto preguntas aquí y en otros sitios donde ocurrieron resultados incorrectos cuando las personas mezclan las uniones implícitas y explícitas (al agregar una combinación izquierda, por ejemplo), por lo que es una mala idea mezclarlas.

Finalmente, muchas personas que usan combinaciones implícitas en realidad no entienden las combinaciones. Esta es una comprensión crítica que debe tener para consultar efectivamente una base de datos.

HLGEM
fuente
Gracias por la explicación. Cuando me enseñaron, nos mostraron ambas sintaxis, pero la diferencia no se explicó. A veces me las arreglé para producir consultas con los lugares faltantes, lo que francamente habría aumentado la cantidad de escritura sobre unirme explícitamente en primer lugar.
Awiebe
8

Decir ah. Simplemente encontré una posible respuesta a mi propia pregunta, mientras miraba la documentación de PostgreSQL . Para resumir lo que explica esta página, la consulta resultante sigue siendo la misma, pero la cantidad de planes que el optimizador debe considerar aumenta exponencialmente con la cantidad de uniones.

Después de aproximadamente seis de tales uniones, el número es tan grande que el tiempo para planificar la consulta puede ser notable, y después de alrededor de diez, el optimizador cambiará de una búsqueda exhaustiva de planes a una búsqueda probabilística, y puede no llegar al plan óptimo. .

Al establecer un parámetro de tiempo de ejecución, puede indicarle al planificador que trate las uniones internas y cruzadas mencionadas explícitamente de manera diferente a las uniones implícitas, forzándolas a la parte superior del plan y sin explorar otras opciones.

Es de destacar que el comportamiento predeterminado es el mismo en cualquier caso, y que obtener planes alternativos requiere conocer los aspectos internos de dbms y las peculiaridades de las tablas en cuestión para obtener un resultado diferente

SingleNegationElimination
fuente
2
Sin embargo, has malinterpretado ligeramente esos documentos. En primer lugar, en realidad hay tres umbrales. Uno dispara el GEQO como usted señaló; los otros dos (desde y límites de colapso de unión) terminan haciendo que la cepilladora se adhiera a elegir índices aplicables en lugar de reorganizar el orden de unión. En segundo lugar, y de igual importancia, las consultas se reescriben a medida que se analizan. Esto da como resultado que la primera de las consultas de ejemplo se analice exactamente en el mismo árbol de consultas que la segunda: los umbrales le permiten a PG saber si debe intentar reordenar las uniones o no.
Denis de Bernardy
8

Bueno, aquí está la visión de la teoría de conjuntos:

Cuando usa una coma para separar dos (o más) nombres de tablas, lo que pretende es el producto cartesiano. Cada fila de la tabla 'izquierda' se 'emparejará' (concatenará) con la de la tabla derecha.

Ahora, si escribe algo en la cláusula where, es como poner una condición en esta 'concatenación' que indica qué filas 'concatenar' con qué filas.

En realidad, esto es "unir" las filas :) y, por lo tanto, la palabra clave de unión que ayuda a proporcionar una sintaxis más legible y es más comprensible que 'realmente' quiera unirse en algunos valores comunes. Similar a lo que @Dustin ha aclarado anteriormente.

Ahora, cada DBMS es inteligente, es decir, no calcula el producto cartesiano primero y luego filtra los datos (extremadamente derrochador), sino que lo hace en función de la estructura de la consulta. Lo único en lo que puedo pensar es que cuando le pides que se una, es como hacer explícita la actividad de unión y probablemente ayude a ejecutar el código más rápido (¿por cuánto? Tendrás que perfilarlo y verlo) pero en el caso separado por comas, necesita algo de tiempo para "descubrir" la estrategia óptima. Puedo estar equivocado, pero solo estoy haciendo una suposición educada sobre cómo se codificaría ...

Doctor
fuente
5

Creo que generalmente es mejor usar declaraciones JOIN para ese caso.

Si, en el futuro, surge una situación que requiere cambiar la declaración de una UNIÓN INTERNA a una UNIÓN EXTERNA, será mucho más fácil hacerlo con la segunda declaración.

Britt Wescott
fuente
3

Cualquier RDBMS hará que sean lo mismo en términos de ejecución. Se trata de si uno es más legible y expresivo.

Use JOIN para que quede claro qué es la combinación de combinaciones y qué es la selección real, como en:

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

vs.

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

El último caso deja en claro de inmediato cuál es la condición de unión y cuál es el criterio de selección.

Andy Lester
fuente
1

Solo una vez he visto los dos resultados en un conjunto diferente de optimizaciones y si la memoria sirve, estaba en ms-sql2k en una consulta realmente complicada. En ese ejemplo, la forma anterior utilizada con * = resultó en un rendimiento aproximadamente 4 veces más rápido. Nadie, incluidos nuestros técnicos de Microsoft, podría explicar por qué. Los chicos de MS lo etiquetaron como un error. Nunca lo he vuelto a ver.

Dado que la mayoría de los RDBMS son lo suficientemente inteligentes como para no hacer los cartesianos completos, la razón más grande por la que puedo pensar en no usarlo (además de que se deprecia) es que la mayoría de las personas menores de 30-35 años con las que he trabajado nunca han visto forma anterior antes y perderse terriblemente cuando lo encuentran.

Cuenta
fuente
Por supuesto, la sintaxis de combinación izquierda nunca proporcionó los resultados correctos de manera confiable (vea BOL para SQL Server 2000), por lo que incluso si fuera más rápido, lo habría reemplazado.
HLGEM
Nunca me encontré con eso, y la búsqueda con el asterisco nunca termina bien, ¿tienes un ejemplo?
Bill
-1

El viejo estilo ha quedado en desuso, no debes usarlo.

Ni siquiera debería haber una discusión sobre cuál es mejor o no. El nuevo código no debería usar la sintaxis anterior.

Pieter B
fuente
Creo que esta respuesta realmente no agrega nada sin decir por qué fue desaprobada y no debe usarse.
RemcoGerlich
1
@RemcoGerlich por qué ha quedado en desuso no está en discusión aquí. Lo que se está discutiendo aquí es si usar la sintaxis antigua o nueva. Si uno es mejor que el otro o no es discutible: no debe usar la sintaxis anterior. La pregunta del por qué es otra discusión. (uno que se resolvió hace 20 años.)
Pieter B
-4

Una razón para la sintaxis más concisa es que es más concisa, por lo que si te sientes cómodo es más fácil de leer. Creo que el caso detallado es similar a escribir aritmética en COBOL, por ejemplo, MULTIPLICAR A POR B DANDO C.

John Bickers
fuente
Votantes: ¿Hay algo de hecho incorrecto en esta respuesta, o fueron simplemente "disgusto contigo"?
Adam Libuša