2011-03-11 17 views
7

¿Existe una diferencia en el rendimiento (en MySQL) entreMySQL: combinación interna vs Dónde

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID 

Y

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID 

?

+3

DUP de http://stackoverflow.com/questions/44917/explicit-vs-implicit-sql-joins – Patrick

Respuesta

10

Como sacado de la respuesta aceptada de que se trate 44917:

En cuanto al rendimiento, que son exactamente los misma (al menos en SQL Server) pero tenga conscientes de que están desaprobación del externa implícita sintaxis de combinación .

En MySql los resultados son los mismos.

Personalmente me quedaría con unir tablas explícitamente ... esa es la manera "socialmente aceptable" de hacerlo.

+0

Encontré la misma respuesta para Oracle, y algunos están de acuerdo en que no hay diferencia para la ejecución. Para Oracle hay una forma de inspeccionar el "plan" para la consulta, ¿hay algo similar en MySQL? – Victor

+0

depende de su software. ¿Qué está utilizando para MySql? Toad para MySQL tiene una pestaña "Explicar plan" para cualquier consulta que cree, pero probablemente no sea exactamente lo que está buscando. Utiliza el comando "EXPLICAR" que Ewan menciona en su respuesta. – Patrick

+0

Acepto que el JOIN explícito es mejor. De hecho, es mucho más seguro y menos propenso a convertirse en CROSS JOIN si olvida alguna parte de la cláusula WHERE. –

0

La coma en una cláusula FROM es una CROSS JOIN. Podemos imaginarnos que SQL Server tiene un procedimiento de ejecución de consulta de selección que de alguna manera debería verse así: 1. iterar a través de cada tabla 2. encontrar filas que cumplan con el predicado de unión y ponerlo en la tabla de resultados. 3. de la tabla de resultados, obtenga solo aquellas filas que cumplan con la condición where.

Si realmente se ve así, el uso de CROSS JOIN en una tabla que tiene unas pocas filas podría asignar mucha memoria, cuando cada fila se combina entre sí antes de examinar la condición. Su servidor SQL podría estar bastante ocupado entonces.

+0

creo que no funciona de esa manera. Si es así, ¿qué pasa si la condición where filtra la primera tabla a un solo registro, entonces solo combinará un registro con la segunda tabla, lo que lo hace realmente rápido? Creo que SQL maneja los datos de otras formas (lo cual solo puedo adivinar). – dxvargas

0

Creo que sí porque el primer ejemplo explícitamente le dice a mysql qué columnas unir y cómo unirlas, donde la segunda tiene que probar mysql y averiguar dónde quieres unirte.

0

la segunda consulta es solo otra notación para una unión interna, por lo que si hay una diferencia en el rendimiento es solo porque una consulta se puede analizar más rápido que la otra, y esa diferencia, si existe, será muy pequeña que no lo notarás

para obtener más información que podría tratar de echar un vistazo a this question (y usar la búsqueda en que la próxima vez antes de hacer una pregunta que ya ha sido respondida)

1

en realidad son prácticamente los mismos, la unión/ON es la sintaxis ANSI más nueva, WHERE es la sintaxis ANSI más antigua. Ambos son reconocidos por los motores de consulta

0

La primera consulta es más fácil de entender para MySQL, por lo que es probable que el plan de ejecución sea mejor y que la consulta se ejecute más rápido.

La segunda consulta sin la cláusula where, es una combinación cruzada. Si MySQL es capaz de entender la cláusula where lo suficientemente bueno, hará todo lo posible para evitar la unión cruzada de todas las filas, pero nada garantiza eso.

En un caso tan simple como el suyo, el rendimiento será estrictamente idéntico.

En cuanto a rendimiento, la primera consulta siempre será mejor o idéntica a la segunda. Y desde mi punto de vista, es mucho más fácil de entender al releer.

10

Son lo mismo.Esto se puede ver mediante la ejecución del comando EXPLAIN:

 
mysql> explain Select * from Table1 T1 
    -> Inner Join Table2 T2 On T1.ID = T2.ID; 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra          | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| 1 | SIMPLE  | T1 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using index         | 
| 1 | SIMPLE  | T2 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using where; Using index; Using join buffer | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
2 rows in set (0.00 sec) 

mysql> explain Select * from Table1 T1, Table2 T2 
    -> Where T1.ID = T2.ID; 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra          | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| 1 | SIMPLE  | T1 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using index         | 
| 1 | SIMPLE  | T2 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using where; Using index; Using join buffer | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
2 rows in set (0.00 sec) 
2

Bueno, una respuesta tardía de mí, como yo estoy analizando el rendimiento de una aplicación antigua que utiliza comas basado en lugar de unirse a INNER JOIN cláusula.

Aquí hay dos tablas que tienen una combinación (ambas tienen registros de más de 1 lac). Al ejecutar la consulta que tiene una unión basada en coma, lleva mucho más tiempo que el caso INNER JOIN.

Cuando analicé la declaración de explicación, encontré que la consulta que tenía una coma estaba usando el buffer de unión. Sin embargo, la consulta que tiene la cláusula INNER JOIN tenía 'using Where'.

También estas consultas son significativamente diferentes, como se muestra en la columna de filas en la consulta de explicación. Estas son mis consultas y sus respectivos resultados de explicación.

explain select count(*) FROM mbst a , his_moneypv2 b 
     WHERE b.yymm IN ('200802','200811','201001','201002','201003') 
     AND a.tel3 != '' 
     AND a.mb_no = b.mb_no 
     AND b.true_grade_class IN (3,6) 
     OR b.grade_class IN (4,7); 

+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 
| id | select_type | table | type  | possible_keys             | key         | key_len | ref | rows | Extra                | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 
| 1 | SIMPLE  | b  | index_merge | PRIMARY,mb_no,yymm,yymm_2,idx_true_grade_class,idx_grade_class | idx_true_grade_class,idx_grade_class | 5,9  | NULL | 16924 | Using sort_union(idx_true_grade_class,idx_grade_class); Using where | 
| 1 | SIMPLE  | a  | ALL   | PRIMARY              | NULL         | NULL | NULL | 134472 | Using where; Using join buffer          | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 

v/s

explain select count(*) FROM mbst a inner join his_moneypv2 b 
     on a.mb_no = b.mb_no 
     WHERE b.yymm IN ('200802','200811','201001','201002','201003') 
     AND a.tel3 != '' 
     AND b.true_grade_class IN (3,6) 
     OR b.grade_class IN (4,7); 

+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+-------+---------------------------------------------------------------------+ 
| id | select_type | table | type  | possible_keys             | key         | key_len | ref    | rows | Extra                | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+-------+---------------------------------------------------------------------+ 
| 1 | SIMPLE  | b  | index_merge | PRIMARY,mb_no,yymm,yymm_2,idx_true_grade_class,idx_grade_class | idx_true_grade_class,idx_grade_class | 5,9  | NULL    | 16924 | Using sort_union(idx_true_grade_class,idx_grade_class); Using where | 
| 1 | SIMPLE  | a  | eq_ref  | PRIMARY              | PRIMARY        | 62  | shaklee_my.b.mb_no |  1 | Using where               | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+------ 
+1

Después de analizar más, encontré que dos restricciones son responsables de esta gran diferencia de rendimiento entre ambas consultas. La condición de primera unión debe ser la primera en la cláusula where antes de cualquier otra condición de filtro. Segundo uso de la instrucción de grupo a grupo que tiene o –

+0

Sus consultas no devuelven las mismas filas. Las filas de unión cruzada con 'b.grade_class IN (4,7)' siempre están en el resultado del primer 'from', pero cuando' a.mb_no = b.mb_no' no están en el resultado del segundo 'from' . Entonces, al comparar las consultas no se dice nada sobre la pregunta. – philipxy

Cuestiones relacionadas