从两个表中选择joid vs Joining两个Selects

时间:2017-02-28 16:09:33

标签: mysql sql oracle join db2

我总是看到人们使用这两种方式加入两个或更多表。

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'

我想知道哪个更快(性能更好),为什么?

2 个答案:

答案 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_idbooks有一个外键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')