Select * from Table1 T1
Inner Join Table2 T2 On T1.ID = T2.ID
和
Select * from Table1 T1, Table2 T2
Where T1.ID = T2.ID
之间的性能(在oracle中)是否存在差异? >
#1 楼
没有!相同的执行计划,请看下面两个表: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
评论
我真的很想看看甲骨文是否有任何官方文件说明这一点
– 4掩护
16年9月6日在11:31
#2 楼
如果查询优化器正在正确地执行其工作,则这些查询之间应该没有区别。它们只是指定相同期望结果的两种方法。评论
是的,效果应该一样。但是SELECT * FROM Table1,Table2 WHERE ...语法是错误的!
–乔尔·科恩(Joel Coehoorn)
08-09-23在15:31
我发现理解FOR INNER JOINS比使用SQL-92语法容易得多。你的旅费可能会改变。
–克雷格商人
08/09/23在17:39
我发现WHERE语法比INNER JION更容易阅读-我猜它像Vegemite。世界上大多数人可能会发现它令人恶心,但孩子长大后喜欢它。
– ScottCher
08-10-27在18:53
素食主义者确实很讨厌,但是我又爱废话了。去搞清楚。
–StingyJack
09年8月27日在12:05
@Darryl我认为联接更容易阅读,因为联接表的条件是立即定义的,而不是在WHERE子句中的“某处”。我更喜欢保留WHERE子句以限制数据集(例如WHERE DATE>(SYSDATE-1)),而不是同时定义表之间的关系(例如WHERE T1.ID = T2.ID)。对于像所讨论的示例这样的小表,差别不大,但是对于涉及多个表和多个条件的大型查询,我认为它使查询更容易理解。
– ImaginaryHuman072889
19年5月24日在17:33
#3 楼
它们应该完全相同。但是,作为编码实践,我宁愿看到Join。它清楚地表达了您的意图,评论
我同意。特别是如果要联接到多个表,则在进行显式联接时解析select语句要容易得多。
–保罗·莫里(Paul Morie)
09年5月19日在16:34
确实。连接表示两组数据之间的语义关系,但其中a表示过滤后的数据集。 +1
–八十一团结
2011年7月19日在9:03
#4 楼
使用JOIN
可以使代码更容易阅读,因为它是不言自明的。速度没有差异(我刚刚测试过),执行计划也相同。
评论
谢谢。我一直在寻找这两种方法之间的速度压缩。
– Farhad Navayazdan
16 Dec 6'在18:21
#5 楼
[为获得加分...]使用JOIN语法使您可以更轻松地注释掉联接,因为联接全部包含在一行中。如果您要调试复杂的查询,这将很有用。
正如其他人所说,它们在功能上是相同的,但是JOIN更清楚了意图声明。因此,它可能会在某些情况下在当前oracle版本中帮助查询优化器(我不知道是否这样做),可能会在Oracle的未来版本中帮助查询优化器(没人知道),或者您更改数据库供应商。
评论
或者...轻松地将INNER JOINS更改为LEFT JOINS,这样您就可以查看导致您错过预期行的联接。之所以这样做,是因为我一次执行了整个查询。如果您将INNER JOINS注释掉,则必须执行消除过程。需要更长的时间。但是为您+1是因为除了可读性之外,这是我最喜欢INNER JOINS的原因之一!
–马修·麦克佩克(Matthew McPeak)
15年8月27日在12:44
#6 楼
我不了解Oracle,但我知道SQL Server中不赞成使用旧语法,并且最终将消失。在新查询中使用旧语法之前,我将检查Oracle打算如何使用它。我更喜欢较新的语法,而不是将联接条件与其他需要的条件混合使用。在较新的语法中,更清楚地说明了什么创建了连接以及正在应用哪些其他条件。在像这样的短查询中,这并不是一个大问题,但是当您拥有更复杂的查询时,它会变得更加混乱。由于人们是在基本查询上学习的,因此我倾向于偏向于人们在复杂查询中需要使用联接语法之前就学习使用联接语法。
同样,我也不是特别了解Oracle,但我知道即使在SQL Server 2000中,旧样式的左连接的SQL Server版本也存在缺陷,并且结果不一致(有时左连接有时会交叉加入),因此永远不要使用它。希望Oracle不会遇到相同的问题,但是可以肯定的是,左右连接可能很难以旧语法正确表达。
此外,根据我的经验(当然,这完全是个人观点,您可能会有不同的经验),使用ANSI I标准联接的开发人员倾向于对联接的含义有更好的了解以及从数据库中获取数据的意义。我相信这是因为大多数了解数据库的人都倾向于编写更复杂的查询,而在我看来,使用ANSI I标准比使用旧样式更易于维护。
评论
阿们哥放下JOINERS !!
– ScottCher
08-10-27在18:55
#7 楼
它们在逻辑上是相同的,但是在采用ANSI语法的Oracle的早期版本中,在更复杂的情况下经常会出现bug,因此在使用它时有时会遇到来自Oracle开发人员的阻力。评论
Oracle的早期版本有此错误吗?多早?什么版本?
– ScottCher
08-10-27在18:53
Metalink拥有详细信息……它们在各处弹出。
–大卫·奥尔德里奇(David Aldridge)
08-10-28在18:32
#8 楼
性能应该是相同的,但是我建议使用join-version,因为它在外部联接方面具有更高的清晰度。 >第三个效果是使用更简单的WHERE条件更易于阅读SQL。
评论
我真的认为关键是标准不明确的意外影响。如果指定联接的类型,那么您将确切地知道所得到的。我发现不同的数据库,甚至同一数据库平台的不同版本在隐式联接中对空值的处理方式也不同。当您指定左/右内/外时,您会花时间思考哪个是正确的。当您使用歧义方法时,您会假定它以您希望/打算使用的方式工作。
– Steve Kallestad
2014年1月15日6:28
#9 楼
不要忘记在Oracle中,只要两个表中的连接键属性都命名相同,您也可以这样写:select *
from Table1 inner join Table2 using (ID);
查询计划,当然。评论
我回滚了该版本,因为先前的版本更改了答案的含义
– juan
2009年6月3日23:37
#10 楼
在表格为第三范式的情况下,表格之间的联接不应更改。即加入客户和付款应始终保持不变。但是,我们应该区分联接和过滤器。
一些作者引用该标准(例如Jim Melton; Alan R. Simon(1993)。《理解新SQL:完整指南》。Morgan) Kaufmann,第11-12页,ISBN 978-1-55860-245-8。)在FROM子句中描述了对逗号分隔的表采用JOIN语法的好处。
我完全同意这种观点。
有几种编写SQL并获得相同结果的方法,但是对于许多团队合作的人来说,源代码的可读性是一个重要方面,并且在明确源代码的意义上,肯定将表之间的关系与特定过滤器分开是一个很大的飞跃。
评论
内连接表示在哪里交叉连接。逗号是交叉连接,其优先级低于关键字连接。对于vs,“过滤器”与内部联接无关。 NF与查询无关。标准中的任何内容都不能通过逗号来促进关键字联接。琐碎的优化可以同时处理。这个答案是一堆误解。
–philipxy
5月13日3:19
1)我猜@philipxy试图说“在FROM FROM子句中,用逗号分隔的表与CROSS JOINed表具有相同的含义”。我同意这一点。当然,您可以坚持使用旧语法,并且可以与JOIN子句共存。 RDBMS优化器将完全理解这两种情况(如果它们当然是等效的),并将制定相同的计划。
– abrittaf
5月14日19:39
#11 楼
在PostgreSQL中,绝对没有区别-它们都等同于相同的查询计划。我99%肯定Oracle也是如此。#12 楼
它们都是内部连接,它们执行相同的操作,只是使用较新的ANSI语法。#13 楼
从功能上讲,它们与前面所说的相同。我同意,尽管这样做可以更好地准确描述您想做什么。很多时候,我一直以为自己知道如何查询某些内容,直到开始进行连接并意识到我想做的查询与我脑中的原始查询不同。#14 楼
的确,从功能上来说,两个查询应以相同的方式处理。但是,经验表明,如果您要从使用新联接语法的视图中进行选择,那么使用它来构造查询也很重要。如果视图使用“ join”语句,那么Oracle的优化器可能会感到困惑,但是访问该视图的查询使用“ where”子句中的传统联接方法。评论
与连接相比,视图的问题更多。
–不存在
08年9月29日在15:04
#15 楼
尽管两个查询的身份似乎很明显,但有时还是会发生一些奇怪的事情。我已经注意到在Oracle 10g中将联接谓词从JOIN移到WHERE时,查询具有不同的执行计划(因为WHERE计划更好),但是我无法在简化的表和数据中重现此问题。我认为这取决于我的数据和统计数据。优化器是一个非常复杂的模块,有时它表现得很神奇。但是我们应该知道答案必须是“无差异”。#16 楼
我今天在检查我们sp的生产中的超时时遇到了一个难题,将xml feed构建的表的内部联接从xml feed更改为'where'子句....现在,平均执行时间是1000次执行中的80ms,而在平均执行时间为2.2秒之前...执行计划的主要区别在于键查找的缺失...在使用这两种方法进行测试之前,您不会知道该消息。评论
多年后,请注意-与更改语法相比,您所观察到的更有可能是重建存储过程的产物。
–莱昂纳多·埃雷拉(Leonardo Herrera)
8月27日14:21
#17 楼
它们都是联接,它们在哪里做同样的事情。#18 楼
正如kiewik所说,执行计划是相同的。JOIN语句更易于阅读,从而更容易避免忘记ON条件并获得笛卡尔积。在使用以下类型的多个联接的长查询中,这些错误可能很难检测到:SELECT * FROM t1,t2 WHERE t1.id = t2.some_field。
如果只忘记一个连接条件,则执行查询的时间很长,返回的记录太多了……真的太多了。一些人使用DISTINCT来修补查询,但执行起来仍然很长。
这正是为什么使用JOIN语句无疑是最佳实践:更好的可维护性和更好的可读性。 />
此外,如果我还记得的话,JOIN在内存使用方面进行了优化。
#19 楼
我还有一个很好的答案:分别定义为SQL92和SQL89,尽管您可以省略INNER(仅使用JOIN即可,而且最简单的查询,您保存了5个键盘笔触,现在想像一下大笔触有多少个笔触)。
评论
仅作记录,我看到查询仅通过从联接更改为where子句来返回不同的结果@BlackTigerX:不同的结果?是否有任何外部联接?因为我看不到内部联接... on与将等效联接条件放入where子句之间会有怎样不同的结果。
旧版本的oracle数据库中不存在join
@MajidTaheri:您谈论的Oracle版本多大? Oracle支持的任何版本都支持JOIN表示法。
根据琐碎的案例,寻找一般的答案或最佳实践。希望看到具有更复杂的where子句的“重新匹配”,涉及多个AND条件。至少在SQL Server中有一个交叉点。