Oracle里另外一些典型的执行计划

在之前的文章里写了Oracle里常见的执行计划,可以参考文章:,这篇文章里介绍的是其他的一些典型的执行计划。

1. AND-EQUAL(INDEX MERGE)

AND-EQUAL又称为INDEX MERGE,顾名思义,INDEX MERGE就是指如果where条件里出现了多个针对不同单列的等值条件,并且这些列上都有单键值的索引,则Oracle可能会以相应的单个等值条件去分别扫描这些索引;然后Oracle会合并这些扫描单个索引所得到的rowid集合,如果能从这些集合中找到相同的rowid,那么这个rowid就是目标SQL最终执行结果所对应的rowid。最后,Oracle只需要用这些rowid回表就能得到目标SQL的最终执行结果。

AND-EQUAL在执行计划中对应的关键字就是“AND-EQUAL”,我们可以使用Hint来强制让Oracle走AND-EQUAL。

看一个实例:

zx@MYDB>create table emp_temp as select * from scott.emp;

 

Table created.

 

zx@MYDB>create index idx_mgr on emp_temp(mgr);

 

Index created.

 

zx@MYDB>create index idx_deptno on emp_temp(deptno);

 

Index created.

 

zx@MYDB>select /*+ and_equal(emp_temp idx_mgr idx_deptno) */ empno,job from emp_temp where mgr=7902 and deptno=20;

 

     EMPNO JOB

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

      7369 CLERK

wKiom1iy0EzBk-5TAABFHiShYhs991.png

从上述显示内容中可以看出,现在此SQL的执行计划走的是对索引IDX_MGR和IDX_DEPTNO的AND-EQUAL。

2. INDEX JOIN

INDEX JOIN很容易引起误解,因为它并不是指通常意义上针对多表的表连接。这里INDEX JOIN指的是针对单表上的不同索引之间的连接。

还以上面的EMP_TEMP为例,已经在列MGR和DEPTNO上分别创建了两个单键值的B*Tree索引,如果此时执行SQL语句“select mgr,deptno from emp_temp”,因为这里要查询的列MGR和DEPTNO均可来源于索引IDX_MGR和IDX_DEPTNO(不考虑NULL值),不用回表,所以除了常规的执行方法之外,Oracle还可以采用如下方法:分别扫描索引IDX_MGR和IDX_DEPTNO,得到的结果集分别记为结果集1和结果集2,然后将结果集1和2做一个连接,连接条件就是“结果集1.rowid=结果集2.rowid”,这样得到的最终连接结果(不用回表)就是上述SQL的执行结果。

很显然,针对上述SQL的INDEX JOIN的执行效率是不如我们直接在列MGR和DEPTNO上建一个组合索引,然后直接扫描该组全索引的效率高。INDEX JOIN只是为CBO提供了一种可选的执行路径,大多数情况下,它只是额外多出的一种选择而已。

看一下例子:

zx@MYDB>delete from emp_temp where mgr is null;

 

1 row deleted.

 

zx@MYDB>commit;

 

Commit complete.

 

zx@MYDB>alter table emp_temp modify mgr not null;

 

Table altered.

 

zx@MYDB>alter table emp_temp modify deptno not null;

 

Table altered.

 

zx@MYDB>select mgr,deptno from emp_temp;

 

       MGR     DEPTNO

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

      7839         10

......

      7698         30

 

13 rows selected.

wKioL1iy0_XSNPUSAAA5h9Oju58248.png

从上述显示内容可以看出,现在目标SQL的执行计划走的是对索引IDX_MGR和IDX_DEPTNO的HASH JOIN。

3. VIEW

Oracle在处理包含视图的SQL时,根据该视图是否能做为视图合并(View Merging),其对应的执行计划有如下两种形式。

如果可以做视图合并,则Oracle在执行该SQL时可以直接针对该视图的基表,此时SQL的执行计划中很可能不会出现关键字“VIEW”(不能完全依赖关键字“VIEW”的出现与否来判断Oracle是否做了视图合并,因为对于某些SQL而言,即使Oracle已经做了视图合并但其所对应的执行计划中可能还会显示关键字“VIEW”)。

如果不能做视图合并,则Oracle将把该视图看作一个整体并独立地执行它,此时SQL的执行计划中将会出现关键字“VIEW”。

看一个实例,还是使用上面的EMP_TEMP表:

zx@MYDB>create view emp_mgr_view as select * from emp_temp where job='MANAGER';

 

View created.

 

zx@MYDB>select empno,sal from emp_mgr_view where ename='CLARK';

 

     EMPNO        SAL

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

      7782       2450

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d635c9385f10fe5e228849c179cafd9e.html