oracle中exists连接两个表,IN、EXISTS、多表连接,哪个速度更快

本帖最后由 ghsau 于 2011-10-11 23:39 编辑

请看下面三个执行计划(Oracle10g)

1.  用IN

SQL> select ename from emp e where e.deptno in (select d.deptno from dept d where d.dname='SALES');

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Plan hash value: 351108634

----------------------------------------------------------------------------------------

| Id   | Operation                                     | Name     | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------

|   0  | SELECT STATEMENT                      |              |     5   |   105 |     5   (0)| 00:00:01 |

|   1  |  NESTED LOOPS                            |              |     5   |   105 |     5   (0)| 00:00:01 |

|   2  |   TABLE ACCESS FULL                     | EMP       |    14  |   126 |     3   (0)| 00:00:01 |

|*  3 |   TABLE ACCESS BY INDEX ROWID   | DEPT      |     1   |    12 |     1   (0)| 00:00:01 |

|*  4 |    INDEX UNIQUE SCAN                   | PK_DEPT |     1  |         |     0   (0)| 00:00:01 |

----------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

3 - filter("D"."DNAME"='SALES')

4 - access("E"."DEPTNO"="D"."DEPTNO")

2. 用EXISTS

SQL> select e.ename from emp e where exists (select 1 from dept d where e.deptno=d.deptno and d.dname='SALES');

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Plan hash value: 90266402

----------------------------------------------------------------------------------------

| Id  | Operation                                     | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                     |             |     5   |   105 |     5   (0)| 00:00:01 |

|   1 |  NESTED LOOPS SEMI                   |              |     5  |   105 |     5   (0)| 00:00:01 |

|   2 |   TABLE ACCESS FULL                   | EMP       |    14  |   126 |     3   (0)| 00:00:01 |

|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPT      |     1   |    12 |     1   (0)| 00:00:01 |

|*  4 |    INDEX UNIQUE SCAN                | PK_DEPT |     1   |         |     0   (0)| 00:00:01 |

----------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

3 - filter("D"."DNAME"='SALES')

4 - access("E"."DEPTNO"="D"."DEPTNO")

3.  用连接

SQL> select e.ename from emp e join dept d on e.deptno=d.deptno where d.dname='SALES';

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Plan hash value: 351108634

----------------------------------------------------------------------------------------

| Id  | Operation                                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                    |                |     5   |   105 |     5   (0)| 00:00:01 |

|   1 |  NESTED LOOPS                           |               |     5   |   105 |     5   (0)| 00:00:01 |

|   2 |   TABLE ACCESS FULL                   | EMP         |    14  |   126 |     3   (0)| 00:00:01 |

|*  3 |   TABLE ACCESS BY INDEX ROWID | DEPT      |     1   |    12   |     1   (0)| 00:00:01 |

|*  4 |    INDEX UNIQUE SCAN                 | PK_DEPT |     1   |          |     0   (0)| 00:00:01 |

----------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

3 - filter("D"."DNAME"='SALES')

4 - access("E"."DEPTNO"="D"."DEPTNO")

按我来看,正常的执行效率应该是3>2>1,但是竟然产生了三个一模一样的执行计划,我原来看过的一个文档是这样说得:

其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了复制代码这是其一,在执行计划里没有体现其二:我们通常是自己选择优化器,还是用Oracle默认的优化器呢?

其三:Oracle10g有三种优化器,CHOOSE/COST/RULE,默认为CHOOSE,当表被analyze过时,选择COST,否则选择RULE,但是ORACLE10g默认分析表的,这里比较迷惑,求解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值