显式与隐式SQL联接

显式与隐式SQL联接,sql,join,Sql,Join,显式与隐式内部联接是否有效率差异? 例如: SELECT * FROM table a INNER JOIN table b ON a.id = b.id; vs 就性能而言,它们完全相同(至少在SQL Server中是如此) PS:请注意,自SQL Server 2005以来,隐式外部联接语法已被弃用。(仍然支持问题中使用的隐式内部联接语法) 就个人而言,我更喜欢联接语法,因为它使表的联接以及联接方式更加清晰。尝试比较较大的SQL查询,从8个不同的表中进行选择,然后在其中进行大量筛选。通过使

显式与隐式内部联接是否有效率差异? 例如:

SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;
vs


就性能而言,它们完全相同(至少在SQL Server中是如此)

PS:请注意,自SQL Server 2005以来,
隐式外部联接
语法已被弃用。(仍然支持问题中使用的
隐式内部联接
语法)


就个人而言,我更喜欢联接语法,因为它使表的联接以及联接方式更加清晰。尝试比较较大的SQL查询,从8个不同的表中进行选择,然后在其中进行大量筛选。通过使用连接语法,可以将表连接的部分与筛选行的部分分开


就性能而言,它们完全相同(至少在SQL Server中是如此),但请注意,它们不支持这种连接语法,SQL Server 2005不支持这种现成的连接语法

我认为您正在考虑弃用的*=和=*运算符与“外部联接”的比较

我刚刚测试了给定的两种格式,它们可以在SQLServer2008数据库上正常工作。在我的例子中,它们产生了相同的执行计划,但我不能自信地说这总是正确的。

在某些数据库(尤其是Oracle)上,连接的顺序会对查询性能产生巨大的影响(如果有两个以上的表)。在一个应用程序中,在某些情况下,我们实际上有两个数量级的差异。如果使用正确的提示语法,使用内部连接语法可以控制此操作


您没有指定正在使用哪个数据库,但概率表明SQL Server或MySQL在哪里没有真正的区别。

@lomaxx:我很确定SQL Serv 2005支持上述两种语法。但是,不支持下面的语法

select a.*, b.*  
from table a, table b  
where a.id *= b.id;

具体来说,不支持外部联接(*=)。

您给出的第一个答案使用了ANSI联接语法,另一个是有效的,可以在任何关系数据库中使用


我同意格罗姆的观点,你应该使用ANSI连接语法。正如他们所说,主要原因是为了清晰。与其使用带有大量谓词的where子句,其中一些谓词连接表,而其他谓词限制使用ANSI join语法返回的行,不如盲目地明确哪些条件用于连接表,哪些条件用于限制结果。

如Leigh Caldwell所述,查询优化器可以根据功能上类似于同一SQL语句的内容生成不同的查询计划。要进一步了解这一点,请查看以下两篇博客帖子:-


我希望您会对此感兴趣。

第二种语法存在不必要的交叉连接的可能性:您可以向FROM部分添加表,而无需相应的WHERE子句。这被认为是有害的。

就性能而言,它不应该有任何区别。显式连接语法对我来说似乎更清晰,因为它清楚地定义了from子句中表之间的关系,并且不会扰乱where子句。

在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)
表1
有166208行<代码>表2大约有1000行


这是一个非常简单的案例;这并不能证明查询优化器在更复杂的情况下不会混淆并生成不同的计划。

根据我的经验,使用交叉连接-with-a-where-clause语法通常会产生大脑受损的执行计划,尤其是在使用Microsoft SQL产品时。例如,SQLServer试图估计表行数的方式非常可怕。使用内部联接语法可以控制查询的执行方式。因此,从实用的角度来看,考虑到当前数据库技术的返祖特性,您必须使用内部连接。

基本上,两者之间的区别在于一种是用旧的方式编写的,而另一种是用现代的方式编写的。就个人而言,我更喜欢使用内部、左侧、外部和右侧定义的现代脚本,因为它们更具解释性,并且使代码更具可读性

在处理内部联接时,可读性也没有真正的区别,但是,在处理左联接和右联接时,可能会变得复杂,因为在旧方法中,您会得到如下结果:

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数据库中看到了两者的混合,有很多人在其中写入,包括老年人和年轻人。同样,它可以归结为脚本的可读性以及与您一起开发的团队。

Leigh,您也可以在隐式联接中使用提示。在Oracle中,联接顺序以有意义的方式影响执行计划的情况极为罕见。请参见Jonathan Lewis的解释。Mike,他们讨论的区别在于,如果指定显式连接,则需要指定要连接的连接条件,而不是筛选器。您会注意到,对于语义正确的查询,exec计划是相同的。坦率地说,即使在SQLServer2000中,我也不会使用它,因为*=语法经常给出错误的答案。有时它会把这些解释为交叉连接。好问题。我很好奇为什么要使用显式连接。是否不可能在没有它的情况下执行所有查询?使用EXPLAIN关键字了解两个查询的区别。。使用JOIN并查看差异。。如果你尝试在一个超过100k条记录的表中进行测试,你可以看到差异…@andrew My question w
SELECT * 
FROM table a 
LEFT JOIN table b ON a.id = b.id;