内在联系与何处


257

两者之间的性能(在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


1
仅作记录,我看到查询仅通过从
联接

12
@BlackTigerX:结果不同吗?是否有任何外部联接?因为我看不到inner join ... onwhere子句中将相等的连接条件与放置相等的连接条件之间会有怎样不同的结果。
香农遣散费

oracle数据库的旧版本中不存在join
MajidTaheri 2012年

2
@MajidTaheri:您谈论的Oracle版本多大?Oracle支持的任何版本都支持JOIN表示法。
乔纳森·莱夫勒

根据琐碎的案例,寻找一般的答案或最佳实践。希望看到具有更复杂的where子句的“重新匹配”,涉及多个AND条件。至少在SQL Server中有一个交叉点。
crokusek

Answers:


195

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

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
我真的很想看看甲骨文是否有任何官方文档对此发表评论
4

68

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


22
是的,效果应该一样。但是SELECT * FROM Table1,Table2 WHERE ...语法是错误的!
Joel Coehoorn

2
我发现理解FOR INNER JOINS比SQL-92语法容易得多。你的旅费可能会改变。
Craig Trader

25
我发现WHERE语法比INNER JION更容易阅读-我猜它像Vegemite。世界上大多数人可能会发现它令人恶心,但孩子长大后喜欢它。
ScottCher

3
素食主义者确实很讨厌,但是我又爱废话了。去搞清楚。
2009年

2
@Darryl我认为JOINs更容易阅读,因为连接表的条件是在此处立即定义的,而不是在WHERE子句中的“某处” 。我更喜欢保留WHERE用于限制数据集的子句(例如WHERE DATE > (SYSDATE - 1)),而不是也定义表之间的关系(例如WHERE T1.ID = T2.ID)。对于像所讨论的示例这样的小表来说,差别不大,但是对于涉及多个表和多个条件的大型查询,我认为这使查询更容易理解。
ImaginaryHuman072889

61

它们应该完全相同。但是,作为编码实践,我宁愿看到Join。它清楚地表达了您的意图,


8
我同意。特别是如果要连接到多个表,则在执行显式连接时解析select语句要容易得多。
保罗·莫里

13
确实。连接表示两组数据之间的语义关系,但其中a表示过滤后的数据集。+1
八十一团结

26

使用JOIN是不言自明的,因此使代码更易于阅读。

速度没有差异(我刚刚测试过),执行计划是相同的。


谢谢。我一直在寻找这两种方法之间的速度压缩。
Farhad Navayazdan '16

14

我不了解Oracle,但我知道SQL Server中不赞成使用旧语法,并且最终将消失。在新查询中使用旧语法之前,我将检查Oracle计划如何使用它。

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

再说一次,我不特别了解Oracle,但我知道即使在SQL Server 2000中,旧样式的左连接的SQL Server版本也存在缺陷,并且结果不一致(有时左连接有时是交叉连接),因此永远不应用过的。希望Oracle不会遇到相同的问题,但是可以肯定的是,用旧语法正确表达左右联接可能会更加困难。

另外,根据我的经验(当然,这完全是个人观点,您可能会有不同的经验),使用ANSI I标准联接的开发人员倾向于更好地了解联接的含义以及获得联接的含义。数据从数据库中移出。我相信这是因为大多数具有良好数据库理解的人都倾向于编写更复杂的查询,而在我看来,使用ANSI I标准要比使用旧样式维护起来容易得多。


1
阿们哥 放下JOINERS !!
ScottCher

14

[加分...]

使用JOIN语法使您可以更轻松地注释掉联接,因为联接全部包含在一行中。如果您要调试复杂的查询,这可能会很有用

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


2
或者...轻松地将INNER JOINS更改为LEFT JOINS,这样您就可以查看导致您错过预期行的联接。之所以这样做,是因为我一次执行了整个查询。如果您将INNER JOINS注释掉,则必须执行消除过程。需要更长的时间。但是为您+1是因为除了可读性之外,这是我最喜欢INNER JOINS的原因之一!
马修·麦克佩克

13

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


Oracle的早期版本有此错误吗?多早?什么版本?
ScottCher

Metalink拥有详细信息……它们在各处弹出。
David Aldridge

7

性能应该是相同的,但是我建议使用join-version,因为当涉及外部联接时,它会提高清晰度。

使用join版本也可以避免意外的笛卡尔积。

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


我真的认为关键是标准不明确的意外影响。如果指定联接的类型,那么您将确切地知道所得到的。我发现不同的数据库,甚至同一数据库平台的不同版本在隐式联接中对空值的处理方式也不同。当您指定左/右内/外时,您会花费时间来思考哪个是正确的。当您使用歧义方法时,您会假定它以您希望/打算使用的方式工作。
史蒂夫·卡列斯塔德

6

不要忘记在Oracle中,只要两个表中的连接键属性都相同,您也可以这样写:

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

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


我rollbacked版本,因为以前的版本改变答案的意义
胡安

5

在表为第三范式的情况下,表之间的联接不应更改。即加入客户和付款应始终保持不变。

但是,我们应该区分joinfilter。联接是关于关系的,而过滤器是关于整体的。

一些作者提到了该标准(例如Jim Melton; Alan R. Simon(1993)。《理解新SQL:完整指南》,Morgan Kaufmann。第11–12页。ISBN 978-1-55860-245-8。) ,他在FROM子句中描述了在逗号分隔的表上采用JOIN语法的好处。

我完全同意这一观点。

有多种方法可以编写SQL并获得相同的结果,但是对于许多团队合作人员而言,源代码的可读性是一个重要方面,并且在明确源代码的意义上,将表之间的相互关系与特定的过滤器分开无疑是一个巨大的飞跃。码。


内连接表示在哪里交叉连接。逗号是交叉连接,其优先级低于关键字连接。对于vs,“过滤器”与内部联接无关。NF与查询无关。标准中的任何内容都不能通过逗号来促进关键字联接。琐碎的优化可以同时处理。这个答案是一堆误解。
philipxy

1)我猜@philipxy试图说“在FROM子句中,用逗号分隔的表与CROSS JOINed表具有相同的含义。” 我同意这一点。当然,您可以坚持使用旧语法,并且可以与JOIN子句共存。RDBMS优化器将完全理解这两种情况(如果它们当然是等效的),并将制定相同的计划。
abrittaf

4

在PostgreSQL中,绝对没有区别-它们都等同于相同的查询计划。我99%确信Oracle也是如此。


2

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


2

从功能上讲,它们与前面所说的相同。我同意,尽管这样做可以更好地准确描述您想做什么。很多时候,我一直以为自己知道如何查询某些内容,直到我开始进行联接并意识到我想做的查询与我脑海中的原始查询不同。


1

在功能上,两个查询的处理方式确实相同。但是,经验表明,如果您要从使用新联接语法的视图中进行选择,那么使用它来构造查询也很重要。如果视图使用“ join”语句,但Oracle的优化器可能会感到困惑,但是访问该视图的查询使用“ where”子句中的传统联接方法。


与连接相比,视图的问题更多。
存在的

0

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

这就是为什么我们通常不能回答这个问题的原因,因为它取决于数据库内部。但是我们应该知道答案必须是“ 无差异 ”。


0

我今天在检查我们sp的生产中的超时时遇到了这个难题,将xml feed构建的表的内部联接从xml feed更改为'where'子句....现在,平均执行时间是1000次执行中的80ms,而在平均执行时间为2.2秒之前...执行计划的主要区别在于键查找的缺失...在使用这两种方法进行测试之前,您不会知道该消息。

干杯。



0

正如kiewik所说,执行计划是相同的。

JOIN语句仅更易于阅读,从而更容易避免忘记ON条件并获得笛卡尔积。使用多个类型为SELECT * FROM t1,t2的联接在长查询中可能很难检测到这些错误,其中t1.id = t2.some_field。

如果您只忘记一个连接条件,那么执行查询的时间将非常长,返回的记录太多了……真的太多了。一些人使用DISTINCT来修补查询,但是执行起来仍然很长。

这正是为什么使用JOIN语句无疑是最佳实践的原因:更好的可维护性和更好的可读性。

此外,如果我还记得,JOIN在内存使用方面进行了优化。


0

我除了这个好答案之外

这就是分别定义为SQL92和SQL89的内容,尽管您可以省略INNER(仅使用JOIN就足够清楚了,在最简单的查询中您保存了5个键盘击键),但是它们之间没有性能差异,现在想象一下有多少个击键那些)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.