【发布时间】:2011-07-13 12:51:52
【问题描述】:
两者之间的性能(在mysql中)是否存在差异
Select * from Table1 T1
Inner Join Table2 T2 On T1.ID = T2.ID
和
Select * from Table1 T1, Table2 T2
Where T1.ID = T2.ID
?
【问题讨论】:
标签: mysql sql performance inner-join
两者之间的性能(在mysql中)是否存在差异
Select * from Table1 T1
Inner Join Table2 T2 On T1.ID = T2.ID
和
Select * from Table1 T1, Table2 T2
Where T1.ID = T2.ID
?
【问题讨论】:
标签: mysql sql performance inner-join
我的一个迟到的答案,因为我正在分析使用基于逗号的连接而不是 INNER JOIN 子句的旧应用程序的性能。
所以这里有两个表,它们有一个连接(两个表的记录都超过 1 lac)。执行具有基于逗号连接的查询时,它比INNER JOIN 的情况要长得多。
当我分析解释语句时,我发现有逗号连接的查询正在使用连接缓冲区。但是,具有INNER JOIN 子句的查询具有“使用Where”。
这些查询也有很大的不同,如解释查询中的行列所示。 这些是我的查询及其各自的解释结果。
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 |
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+------
【讨论】:
b.grade_class IN (4,7) 的交叉连接行总是在第一个from 的输出中,但是当a.mb_no = b.mb_no 时它们不在第二个from 的输出中。因此,比较查询不会告诉您有关问题的任何信息。
它们是一样的。这可以通过运行EXPLAIN 命令看到:
【讨论】:
第一个查询对于 MySQL 来说更容易理解,因此执行计划可能会更好,并且查询会运行得更快。
没有 where 子句的第二个查询是交叉连接。如果 MySQL 能够很好地理解 where 子句,它会尽量避免交叉连接所有行,但不能保证这一点。
在像您这样简单的情况下,性能将完全相同。
在性能方面,第一个查询总是比第二个更好或相同。而且从我的角度来看,重读时也更容易理解。
【讨论】:
实际上它们几乎相同,JOIN / ON 是较新的 ANSI 语法,WHERE 是较旧的 ANSI 语法。两者都被查询引擎识别
【讨论】:
第二个查询只是内连接的另一种表示法,所以如果在性能上存在差异,那只是因为一个查询的解析速度比另一个查询快 - 如果存在差异,那么差异将非常小,以至于你不会注意到的。
有关更多信息,您可以尝试查看this question(并在下次询问已回答的问题之前使用 SO 上的搜索)
【讨论】:
从问题 44917 中接受的答案中得出:
在性能方面,它们正是 相同(至少在 SQL Server 中)但是是 意识到他们正在弃用 隐式外连接语法。
在 MySql 中结果是一样的。
我个人会坚持明确加入表格...这是“社会可接受的”方式。
【讨论】:
我会这样认为,因为第一个示例明确告诉 mysql 要加入哪些列以及如何加入它们,第二个 mysql 必须尝试找出您要加入的位置。
【讨论】:
FROM 子句中的逗号是 CROSS JOIN。我们可以想象 SQL Server 有一个选择查询执行过程,它看起来应该是这样的: 1.遍历每个表 2. 找到满足连接谓词的行并将其放入结果表中。 3. 从结果表中,只获取满足where条件的行。
如果看起来确实如此,那么在检查 where 条件之前,在每行相互组合时,对具有数千行的表使用 CROSS JOIN 可能会分配大量内存。那时您的 SQL 服务器可能会很忙。
【讨论】: