根据索引的类型与where限制条件的不同有种类型的Oracle索引扫描
() 索引唯一扫描(index unique scan)
() 索引范围扫描(index range scan)
() 索引全扫描(index full scan)
() 索引快速扫描(index fast full scan)
一 索引唯一扫描(index unique scan)
通过唯一索引查找一个数值经常返回单个ROWID如果该唯一索引有多个列组成(即组合索引)则至少要有组合索引的引导列参与到该查询中如创建一个索引create index idx_test on emp(ename deptno loc)则select ename from emp where ename = JACK and deptno = DEV语句可以使用该索引如果该语句只返回一行则存取方法称为索引唯一扫描而select ename from emp where deptno = DEV语句则不会使用该索引因为where子句种没有引导列如果存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)的话Oracle经常实现唯一性扫描
如
SQL> set autot traceonly exp; 只显示执行计划
SQL> select * from scottemp t where tempno=;
执行计划
Plan hash value:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
| | SELECT STATEMENT | | | | ()| :
| | TABLE ACCESS BY INDEX ROWID| EMP | | | ()| :
|* | INDEX UNIQUE SCAN | PK_EMP | | | ()| :
Predicate Information (identified by operation id):
access(TEMPNO=)
二.索引范围扫描(index range scan)
使用一个索引存取多行数据同上面一样如果索引是组合索引而且select ename from emp where ename = JACK and deptno = DEV语句返回多行数据虽然该语句还是使用该组合索引进行查询可此时的存取方法称为索引范围扫描
在唯一索引上使用索引范围扫描的典型情况下是在谓词(where限制条件)中使用了范围操作符(如><<>>=<=between)
使用索引范围扫描的例子
SQL> select empnoename from scottemp where empno > order by empno;
执行计划
Plan hash value:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
| | SELECT STATEMENT | | | | ()| :
| | TABLE ACCESS BY INDEX ROWID| EMP | | | ()| :
|* | INDEX RANGE SCAN | PK_EMP | | | ()| :
Predicate Information (identified by operation id):
access(EMPNO>)
在非唯一索引上谓词可能返回多行数据所以在非唯一索引上都使用索引范围扫描
使用index rang scan的种情况
(a) 在唯一索引列上使用了range操作符(> < <> >= <= between)
(b) 在组合索引上只使用部分列进行查询导致查询出多行
(c) 对非唯一索引列上进行的任何查询
三.索引全扫描(index full scan)
与全表扫描对应也有相应的全Oracle索引扫描在某些情况下可能进行全Oracle索引扫描而不是范围扫描需要注意的是全Oracle索引扫描只在CBO模式下才有效 CBO根据统计数值得知进行全Oracle索引扫描比进行全表扫描更有效时才进行全Oracle索引扫描而且此时查询出的数据都必须从索引中可以直接得到
全Oracle索引扫描的例子
SQL> create index big_emp on scottemp(empnoename);
索引已创建
SQL> select empno ename from scottemp order by empnoename;
执行计划
Plan hash value:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| | SELECT STATEMENT | | | | ()| :: |
| | INDEX FULL SCAN | BIG_EMP | | | ()| :: |
四. 索引快速扫描(index fast full scan)
扫描索引中的所有的数据块与 index full scan很类似但是一个显着的区别就是它不对查询出的数据进行排序即数据不是以排序顺序被返回在这种存取方法中可以使用多块读功能也可以使用并行读入以便获得最大吞吐量与缩短执行时间
索引快速扫描的例子
SQL> select /*+ index_ffs(dave index_dave) */ id from dave where id>;
执行计划
Plan hash value:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
| | SELECT STATEMENT | | | | ()| ::
|* | INDEX FAST FULL SCAN| INDEX_DAVE | | | ()| ::
Predicate Information (identified by operation id):
filter(ID>)
为了实现这个效果折腾了半天最终还是用hint来了