显式与隐式内连接有效率差异吗? 例如:
SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;
VS
SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;
答案 0 :(得分:122)
性能方面,它们完全相同(至少在SQL Server中)。
PS:请注意,自SQL Server 2005以来已弃用IMPLICIT OUTER JOIN
语法。(仍然支持问题中使用的IMPLICIT INNER JOIN
语法)
Deprecation of "Old Style" JOIN Syntax: Only A Partial Thing
答案 1 :(得分:120)
我个人更喜欢连接语法,因为它更清楚地表了表的连接以及它们的连接方式。尝试比较较大的SQL查询,从8个不同的表中进行选择,并在那里进行大量过滤。通过使用连接语法,可以将表连接的部分分离到过滤行的部分。
答案 2 :(得分:45)
在MySQL 5.1.51上,两个查询都有相同的执行计划:
mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| 1 | SIMPLE | b | ALL | PRIMARY | NULL | NULL | NULL | 986 | |
| 1 | SIMPLE | a | ref | pid | pid | 4 | schema.b.pid | 70 | |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.02 sec)
mysql> explain select * from table1 a, table2 b where a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| 1 | SIMPLE | b | ALL | PRIMARY | NULL | NULL | NULL | 986 | |
| 1 | SIMPLE | a | ref | pid | pid | 4 | schema.b.pid | 70 | |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.00 sec)
table1
有166208行; table2
有大约1000行。
这是一个非常简单的案例;它没有任何方法证明查询优化器不会混淆并在更复杂的情况下生成不同的计划。
答案 3 :(得分:33)
第二种语法具有交叉连接的不必要的可能性:您可以将表添加到FROM部分而不使用相应的WHERE子句。这被认为是有害的。
答案 4 :(得分:14)
您给出的第一个答案使用了所谓的ANSI连接语法,另一个是有效的,可以在任何关系数据库中使用。
我同意grom你应该使用ANSI连接语法。正如他们所说,主要原因是为了清晰起见。而不是让where子句有很多谓词,其中一些连接表和其他限制使用ANSI连接语法返回的行的其他方法,你正在明确地清楚哪些条件用于连接表,哪些条件用于限制结果
答案 5 :(得分:6)
@lomaxx:为了澄清,我非常肯定SQL Serv 2005支持上述两种语法。不支持下面的语法
select a.*, b.*
from table a, table b
where a.id *= b.id;
具体而言,不支持外连接(* =)。
答案 6 :(得分:4)
性能方面,它们完全相同(至少在SQL Server中),但请注意它们不赞成使用此连接语法,并且sql server2005不支持它。
我认为您正在考虑弃用的* =和= *运算符与“外部联接”。
我刚刚测试了给出的两种格式,它们在SQL Server 2008数据库上正常运行。在我的情况下,他们产生了相同的执行计划,但我无法自信地说这总是如此。
答案 7 :(得分:2)
在某些数据库(尤其是Oracle)上,连接的顺序可能会对查询性能产生巨大影响(如果有两个以上的表)。在一个应用中,我们在某些情况下实际上有两个数量级的差异。使用内部联接语法可以控制它 - 如果使用正确的提示语法。
你没有指定你正在使用哪个数据库,但是概率表明SQL Server或MySQL没有真正的区别。
答案 8 :(得分:1)
正如Leigh Caldwell所说,查询优化器可以基于功能上看起来像相同的SQL语句来生成不同的查询计划。有关此内容的进一步阅读,请查看以下两篇博客文章: -
One posting from the Oracle Optimizer Team
Another posting from the "Structured Data" blog
我希望你觉得这很有意思。
答案 9 :(得分:1)
性能方面,它应该没有任何区别。显式连接语法对我来说似乎更清晰,因为它清楚地定义了from子句中的表之间的关系,并且不会使where子句混乱。
答案 10 :(得分:0)
根据我的经验,使用cross-join-with-a-where子句语法通常会产生脑损坏的执行计划,尤其是在使用Microsoft SQL产品时。例如,SQL Server尝试估计表行计数的方式是非常可怕的。使用内部联接语法可以控制查询的执行方式。所以从实际的角度来看,鉴于当前数据库技术的优点,你必须使用内连接。
答案 11 :(得分:0)
基本上,两者之间的区别在于,一种是以旧的方式编写的,而另一种是以现代的方式编写的。就我个人而言,我更喜欢使用内部,左侧,外部,右侧定义的现代脚本,因为它们更具解释性,并且使代码更具可读性。
在处理内部联接时,可读性也没有实质性的区别,但是,在处理左右联接时,它可能会变得复杂,就像在较旧的方法中,您会得到如下所示:
SELECT *
FROM table a, table b
WHERE a.id = b.id (+);
以上是编写左联接的旧方法,而不是以下内容:
SELECT *
FROM table a
LEFT JOIN table b ON a.id = b.id;
如您所见,脚本的现代编写方式使查询更具可读性。 (顺便说一句,对于右联接,对于外联接,则稍微复杂一些。)
回到样板,对SQL编译器没有什么影响,因为查询以相同的方式处理查询。我已经在Oracle数据库中看到了两者的混合情况,这些数据库中有很多人在写它,无论是老年人还是年轻人。再次,归结为脚本的可读性和与您一起开发的团队。