我总是看到人们使用这两种方式加入两个或更多表。
select *
from BOOKS as B
where B.name = 'GOOD BOOK'
inner join select *
from AUTHOR as A
where A.AUTHOR_NAME = 'GOOD AUTHOR' on B.BOOK_ID = A.BOOK_ID
select *
from BOOKS as B
inner join AUTHOR as A on B.BOOK_ID = A.BOOK_ID
where B.name = 'GOOD BOOK'
and A.AUTHOR_NAME = 'GOOD AUTHOR'
我想知道哪个更快(性能更好),为什么?
答案 0 :(得分:0)
即使语法错误,您的意图也很明确。使用Oracle语法(我认为下面两个查询的所有SQL标准都是如此),您想知道将WHERE条件分别应用于每个表是否更有效,然后再进行连接,或者是否更便宜连接然后将WHERE条件应用于连接的行。
答案是,在几乎所有情况下,首先应用WHERE条件应该更便宜 - 特别是如果您有索引以及可以用于有效访问基表行的索引。这是因为几乎总是访问硬盘上的行的I / O是最耗时的操作或者是最耗时的操作之一。使用索引,在CPU中发生任何操作之前,查询引擎可能只能从一个表或另一个(或两者)中读取少量行。
话虽如此,只说甲骨文(我认识的唯一一个),你需要的是两件事:(1)熟悉谷歌,(2)搜索的短语,即"谓词推&#34 ;.在像您这样简单的情况下,Oracle优化器将推送"推送"即使您使用第二种语法,每个基表的谓词(WHERE条件)。如果您为第二个查询运行解释计划,则可以轻松查看。
为了完整性,这是两个查询的正确语法。 (一般来说,你不应该在SELECT子句中使用* - 你应该单独命名列 - 但你没有描述任何实际的表,所以我别无选择。)
select *
from (select * from books where name = 'Good Book' ) b
inner join
(select * from authors where name = 'Good Author') a
on b.book_id = a.book_id
(顺便说一下,这是一个奇怪的安排 - 我宁愿期望authors
表让主键author_id
和books
有一个外键author_id
引用{ {1}},并且联接将在这些列上......但是,我再次理解这不是实际设置。)
<强>与强>
authors
答案 1 :(得分:0)
我拿了两个例子并使用EMP和DEPT重新编写了它们(在Oracle中)。我相信这些查询代表了你要做的事情;如果没有,请随时纠正我。我还添加了@ mathguy的例子(重写)
select *
from EMP E
inner join ( select *
from DEPT D
where d.loc = 'DALLAS' ) d1
on d1.deptno = e.deptno
where e.job = 'CLERK'
select *
from DEPT D
inner join EMP E
on D.deptno = E.deptno
where d.loc = 'DALLAS'
and e.job = 'CLERK'
select *
from ( select * from dept where loc = 'DALLAS' ) D
inner join
( select * from emp where job = 'CLERK' ) E
on e.deptno = d.deptno
我为所有查询生成了执行计划,事实证明它们都是一样的。 Oracle将执行基于成本的转换 - 基本上重写您的查询以生成最佳执行计划。执行计划如下:
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4 (100)| |
|* 1 | HASH JOIN | | 1 | 59 | 4 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| DEPT | 1 | 20 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| EMP | 4 | 156 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("E"."DEPTNO"="D"."DEPTNO")
2 - filter("D"."LOC"='DALLAS')
3 - filter("E"."JOB"='CLERK')