内连接vs其中

时间:2008-09-23 15:13:28

标签: sql performance oracle

之间的性能(在oracle中)是否存在差异
Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

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

19 个答案:

答案 0 :(得分:188)

没有!相同的执行计划,请看这两个表:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

使用内部联接的查询的执行计划:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

使用WHERE子句进行查询的执行计划。

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

答案 1 :(得分:65)

如果查询优化器正在执行其工作,那么这些查询之间应该没有区别。它们只是两种指定相同结果的方法。

答案 2 :(得分:59)

他们应该完全一样。但是,作为编码实践,我宁愿看到加入。它清楚地表达了你的意图,

答案 3 :(得分:26)

使用JOIN使代码更易于阅读,因为它不言自明。

速度没有区别(我刚刚测试过它),执行计划是一样的。

答案 4 :(得分:15)

我不了解Oracle,但我知道旧语法在SQL Server中已被弃用,最终会消失。在我在新查询中使用旧语法之前,我会检查Oracle计划用它做什么。

我更喜欢较新的语法,而不是将连接条件与其他条件混合使用。在更新的语法中,更清楚的是创建连接以及正在应用的其他条件。在像这样的简短查询中并不是一个大问题,但是当你有一个更复杂的查询时,它会变得更加混乱。由于人们在基本查询上学习,我倾向于更喜欢人们在复杂查询中需要之前学习使用连接语法。

我再也不认识Oracle,但我知道旧版左连接的SQL Server版本即使在SQL Server 2000中也存在缺陷,并且会产生不一致的结果(有时候左边的连接有时是交叉连接),所以它永远不应该使用。希望Oracle不会遇到同样的问题,但肯定左右连接可能更难以在旧语法中正确表达。

另外,我的经验(当然这完全是个人观点,你可能有不同的经验)使用ANSII标准加入的开发人员倾向于更好地理解连接是什么以及它意味着什么从数据库中获取数据的条款。我相信这是因为大多数具有良好数据库理解力的人倾向于编写更复杂的查询,而且在我看来,使用ANSII标准比使用旧样式更容易维护。

答案 5 :(得分:13)

[奖励积分......]

使用JOIN语法可以更轻松地将连接注释掉,因为它全部包含在一行中。如果要调试复杂查询,可以

正如其他人所说,它们在功能上是相同的,但是JOIN更清楚地表达意图。因此,可能在某些情况下帮助查询优化器在当前的oracle版本中(我不知道是否这样做),它可能在未来的Oracle版本中帮助查询优化器(没有人有任何想法),或者如果您更改数据库供应商,可能有帮助。

答案 6 :(得分:13)

它们在逻辑上是相同的,但在采用ANSI语法的早期版本的Oracle中,在更复杂的情况下经常会出现错误,因此在使用它时有时会遇到Oracle开发人员的阻力。

答案 7 :(得分:7)

性能应该相同,但我建议使用join-version,因为外部连接的清晰度会提高。

使用join-version也可以避免无意识的笛卡尔积。

第三个效果是使用更简单的WHERE条件更容易读取SQL。

答案 8 :(得分:6)

不要忘记在Oracle中,如果两个表中的连接键属性命名相同,您也可以将其写为:

select *
from Table1 inner join Table2 using (ID);

当然,这也有相同的查询计划。

答案 9 :(得分:3)

在PostgreSQL中,肯定没有区别 - 它们都等同于同一个查询计划。我99%肯定甲骨文的情况也是如此。

答案 10 :(得分:3)

在表格为第3范式的情况下,表格之间的连接不应更改。即加入CUSTOMERS和PAYMENTS应该始终保持不变。

但是,我们必须将加入过滤器区分开来。联接是关于关系,过滤器是关于分割整体。

SQL-92语法鼓励我们将这两个概念分开,并且它优先于在WHERE子句上放置连接和过滤器的旧语法,这更加麻烦。

答案 11 :(得分:2)

在功能上它们与已经说过的相同。我同意,虽然进行连接更适合描述你想要做什么。很多次我以为我知道自己想要查询的东西,直到我开始进行连接,并意识到我想要做的不同于我头脑中的原始查询。

答案 12 :(得分:1)

确实,在功能上,两个查询都应该以相同的方式处理。但是,经验表明,如果从使用新连接语法的视图中进行选择,则使用它构建查询也很重要。如果视图使用“join”语句,Oracle的优化器可能会混淆,但访问视图的查询使用传统方法加入“where”子句。

答案 13 :(得分:1)

它们都是内部联接,它们执行相同的操作,只使用较新的ANSI语法。

答案 14 :(得分:0)

虽然两个查询的身份似乎很明显,但有时会发生一些奇怪的事情。在将连接谓词从JOIN移动到Oracle 10g中的WHERE(对于WHERE计划更好)时,我已经得到了具有不同执行计划的查询,但我无法在简化表和数据中重现此问题。我认为这取决于我的数据和统计数据。优化器是一个非常复杂的模块,有时它表现得很神奇。

这就是为什么我们不能回答这个问题,因为它取决于DB内部。但我们应该知道答案必须是没有差异'。

答案 15 :(得分:0)

我今天遇到了这个难题,当时检查我们的一个生产时间,将一个由xml Feed构建的桌子上的内部连接改为“'相反......平均执行时间现在是1000次执行时的80ms,而平均执行时间是2.2秒......执行计划的主要区别在于密钥查找的消失...直到你的消息是你不会知道的使用两种方法测试。

欢呼声。

答案 16 :(得分:0)

他们都是联盟,也是同样的事情。

查看In MySQL queries, why use join instead of where?

答案 17 :(得分:0)

正如kiewik所说,执行计划是一样的。

JOIN语句更容易阅读,更容易忘记ON条件和获取笛卡尔积。在使用多个类型的连接的长查询中很难检测到这些错误:SELECT * FROM t1,t2 WHERE t1.id = t2.some_field。

如果你只忘记一个连接条件,你会得到一个很长的执行查询,返回太多记录......真的太多了。有些人使用DISTINCT修补查询,但执行时间仍然很长。

准确地说,使用JOIN语句肯定是最佳做法:更好的可维护性和更好的可读性。

此外,如果我记得,JOIN会针对内存使用进行优化。

答案 18 :(得分:0)

the mysqljs documentation之外,我还有一个补充:

分别定义为SQL92和SQL89,尽管您可以省略INNER(仅使用JOIN就足够清楚了,并且在最简单的查询中您保存了5个键盘击键),但是它们之间没有性能差异。大)。