使用索引快速全扫(index ffs) 来避免全表扫描 参考原文: index fast full scan usage to avoid full table scans (doc id 70135.1) 适用于: oracle database - enterprise edition - version 7.3.0.0 to 11.2.0.3 [release 7.3.0 to 11.2] information i
使用索引快速全扫(index ffs) 来避免全表扫描
参考原文:
index fast full scan usage to avoid full table scans (doc id 70135.1)
适用于:
oracle database - enterprise edition - version 7.3.0.0 to 11.2.0.3 [release 7.3.0 to 11.2]
information in this document applies to any platform.
***checked for relevance on 2-dec-2013***
目的:
本文讨论了使用 index fast full scans (index ffs) 来避免full table scans (fts)
范围:
那些遇到 查询走fts而不走index ffs这种情况 的支持分析人员和客户
细节:
什么时候index ffs 优先于fts 被使用?
从oracle8 server concepts manual:
1.索引必须包括所有的在查询中出现的列(确切的说是要么 出现在select之后,要么 出现在where 之后)。
2.index ffs 只适用于cbo
3.index ffs 对应的hint为 /*+ index_ffs() */
index ffs是在oracle 7.3中被引入的。
在oracle 7中,需要把初始化参数v733_plans_enabled设置为true
一个index ffs 将会扫描index中的所有blocks。返回的数据是不排序的。
index ffs 可以使用多块i/o,也可以像 fts那样使用并行。
例子:
使用 the standard emp and dept tables 来举例
准备工作:创建一个复合索引
create index emp_ix on emp(empno, deptno, ename);
第一种情况:查询一个单表,该查询的 select语句之后有索引中的全部列:
sql> select /*+ index_ffs (emp emp_ix) */ empno, deptno, ename from emp;
execution plan
----------------------------------------------------------
0 select statement optimizer=choose (cost=4 card=21 bytes=693)
1 0 index (fast full scan) of 'emp_ix' (non-unique) (cost=4 card=21 bytes=693)
第二种情况:查询一个单表, 组成index的列,要么 出现在select之后,要么 where 之后
sql> select /*+ index_ffs (emp emp_ix) */ empno, ename from emp where deptno > :bind1;
execution plan
----------------------------------------------------------
0 select statement optimizer=choose (cost=4 card=2 bytes=66)
1 0 index (fast full scan) of 'emp_ix' (non-unique) (cost=4 card=2 bytes=66)
第三种情况:查询中有构成index的所有列和没在index中的列
sql> select /*+ index_ffs (emp emp_ix) */ empno, ename from emp where deptno > :bind1 and sal execution plan
----------------------------------------------------------
0 select statement optimizer=choose (cost=1 card=1 bytes=46)
1 0 table access (full) of 'emp' (cost=1 card=1 bytes=46)
note: cbo 优化器选择了 fts,原因是 index ffs不能满足 all columns in query 这个要求。
--->可以看出,虽然用了hint,但是执行计划依然不走index ffs,而是走了table access (full)。原因很简单:走了index ffs就得不到正确的结果。
第四种情况:构成复合索引的列,包括在查询中。
sql> select /*+ index_ffs (emp emp_ix) */ ename from emp;
execution plan
----------------------------------------------------------
0 select statement optimizer=choose (cost=4 card=21 bytes=147)
1 0 index (fast full scan) of 'emp_ix' (non-unique) (cost=4 card=21 bytes=147)
note: index ffs still chosen if subset of index columns in query
第五种情况:查询包括关联(join)
sql> select /*+ index_ffs ( e emp_ix) */ e.ename, d.dname from emp e , dept d where e.deptno=d.deptno;
execution plan
----------------------------------------------------------
0 select statement optimizer=choose (cost=6 card=4 bytes=168)
1 0 hash join (cost=6 card=4 bytes=168)
2 1 index (fast full scan) of 'emp_ix' (non-unique) (cost=4card=21 bytes=420)
3 1 table access (full) of 'dept' (cost=1 card=21 bytes=462)
--->可以看到,对emp表(即:e表),也是能走index ffs