题
显式内连接与隐式内连接之间有效率差异吗?例如:
SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;
与
SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;
解决方案
性能方面,它们完全相同(至少在 SQL Server 中)。
附:请注意, IMPLICIT OUTER JOIN
自 SQL Server 2005 以来,该语法已被弃用。(这 IMPLICIT INNER JOIN
问题中使用的语法仍然受支持)
其他提示
就我个人而言,我更喜欢联接语法,因为它可以更清楚地表明表的联接以及它们的联接方式。尝试比较较大的 SQL 查询,您从 8 个不同的表中进行选择,并且在其中进行了大量过滤。通过使用连接语法,您可以将连接表的部分与过滤行的部分分开。
在 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 行。
这是一个非常简单的案例;它无论如何都不能证明查询优化器不会在更复杂的情况下感到困惑并生成不同的计划。
第二种语法存在交叉连接的不良可能性:您可以将表添加到 FROM 部分,而无需相应的 WHERE 子句。这被认为是有害的。
您给出的第一个答案使用所谓的 ANSI 连接语法,另一个答案是有效的并且适用于任何关系数据库。
我同意 grom 的观点,您应该使用 ANSI 连接语法。正如他们所说,主要原因是为了清晰。与其使用包含大量谓词的 where 子句(其中一些谓词连接表,另一些则限制使用 ANSI 连接语法返回的行),您可以非常清楚哪些条件用于连接表,哪些条件用于限制结果。
@lomaxx:澄清一下,我非常确定 SQL Serv 2005 支持上述两种语法。但是不支持以下语法
select a.*, b.*
from table a, table b
where a.id *= b.id;
具体来说,不支持外连接 (*=)。
在性能方面,它们是完全相同的(至少在 SQL Server 中),但请注意,它们正在弃用此连接语法,并且 sql server2005 不支持它。
我认为您正在考虑已弃用的 *= 和 =* 运算符与已弃用的运算符。“外连接”。
我刚刚测试了给出的两种格式,它们在 SQL Server 2008 数据库上正常工作。就我而言,他们产生了相同的执行计划,但我不能自信地说这永远是正确的。
在某些数据库(特别是 Oracle)上,连接的顺序会对查询性能产生巨大的影响(如果有两个以上的表)。在一个应用程序中,在某些情况下我们确实存在两个数量级的差异。使用内连接语法可以让您控制这一点 - 如果您使用正确的提示语法。
您没有指定您正在使用哪个数据库,但很可能建议使用 SQL Server 或 MySQL,这两者没有真正的区别。
正如 Leigh Caldwell 所说,查询优化器可以根据功能上相似的 SQL 语句生成不同的查询计划。要进一步阅读此内容,请查看以下两篇博客文章:-
我希望你觉得这很有趣。
就性能而言,它应该没有任何区别。显式联接语法对我来说似乎更清晰,因为它清楚地定义了 from 子句中的表之间的关系,并且不会混淆 where 子句。
根据我的经验,使用带有 where 子句的交叉连接语法通常会产生大脑损伤的执行计划,特别是当您使用 Microsoft SQL 产品时。例如,SQL Server 尝试估计表行数的方式非常糟糕。使用内连接语法可以让您对查询的执行方式进行一些控制。因此,从实际角度来看,考虑到当前数据库技术的返祖性质,您必须采用内连接。
基本上,两者之间的区别在于,一种是用旧方式编写的,另一种是用现代方式编写的。就我个人而言,我更喜欢使用内部、左、外部、右定义的现代脚本,因为它们更具解释性,并使代码更具可读性。
在处理内部联接时,可读性也没有真正的区别,但是,在处理左联接和右联接时可能会变得复杂,就像在旧方法中一样,您会得到如下所示的结果:
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 数据库中看到了这两种情况的混合,有很多人(无论是年长的还是年轻的)都在其中写入内容。同样,这归结为脚本的可读性以及与您一起开发的团队。