根据索引的类型与where限制条件的不同,有4种类型的Oracle索引扫描: 3,4可归一种
(1) 索引唯一扫描(index uniquescan)
(2) 索引范围扫描(index range scan)
(3) 索引全扫描(index full scan)
(4) 索引快速扫描(index fast full scan)
(5) 索引跳跃扫描(INDEXSKIP SCAN)
一. 索引唯一扫描(index unique scan)
通过唯一索引查找一个数值经常返回单个ROWID,存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)的话,Oracle经常实现唯一性扫描
1 必须是通过唯一索引【UNIQUE】来访问数据;
2 通过唯一索引来访问数据时,每次返回的记录数必须是1条;
3 WHERE从句中必须要用等值【=】条件来过滤数据:
注意:表中某个字段是唯一的,如果该字段上的索引不是唯一的,那么CBO选择的将是通过INDEX RANGE SCAN的路径来访问数据。想要表达的是,真实场景下这种情况的确会存在,因为有些系统是通过应用程序来保证表中的字段唯一,而并没有在表上对应的字段上通过创建唯一约束或者是唯一索引来保证数据的唯一性。那么,这样的话,将会导致CBO在选择执行计划的情况下,有可能会出现偏差。所以,对于这种情况下,即使应用程序可以保证数据的唯一性,最好还是在表上创建一个唯一索引比较稳妥。
例子:
SQL> create table t as select * from dba_objects where object_id is not null;
表已创建。
SQL> alter table t modify (object_id not null);
表已更改。
SQL> create unique index index_t on t(object_id);
索引已创建。
SQL> select * from t a where a.object_id=75780;
执行计划
----------------------------------------------------------
Plan hash value: 4119349871

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

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

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

|   0 | SELECT STATEMENT            |         |     1 |   207 |     2   (0)| 00:

|   1 |  TABLE ACCESS BY INDEX ROWID| T       |     1 |   207 |     2   (0)| 00:

|*  2 |   INDEX UNIQUE SCAN         | INDEX_T |     1 |       |     1   (0)| 00:

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

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("A"."OBJECT_ID"=75780)

统计信息
----------------------------------------------------------
          6  recursive calls
          0  db block gets
         12  consistent gets
          1  physical reads
          0  redo size
       1348  bytes sent via SQL*Net to client
        404  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
二.索引范围扫描(index range scan)
使用一个索引存取多行数据,或者创建索引时没有提字为unique索引,即使返一行记录也走范围扫描.
使用index rang scan的3种情况:
(a) 在唯一索引列上使用了range操作符(> < <> >= <= between)。
(b) 在组合索引上(unique index),只使用部分列进行查询,导致查询出多行。
(c) 对非唯一索引列上进行的任何查询。

例子:
SQL> create table t as select * from dba_objects where object_id is not null;
表已创建。
SQL> alter table t modify (object_id not null);
表已更改。
SQL> create index index_t on t(object_id);
索引已创建。
SQL> set wrap off;
SQL> set autotrace traceonly;
SQL> select * from t a where a.object_id = 75780;
Plan hash value: 80339723

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

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

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

|   0 | SELECT STATEMENT            |         |     1 |   207 |     2   (0)| 00:

|   1 |  TABLE ACCESS BY INDEX ROWID| T       |     1 |   207 |     2   (0)| 00:

|*  2 |   INDEX RANGE SCAN          | INDEX_T |     1 |       |     1   (0)| 00:

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

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("A"."OBJECT_ID"=75780)

Note
-----
   - dynamic sampling used for this statement (level=2)

统计信息
----------------------------------------------------------
         37  recursive calls
          0  db block gets
        118  consistent gets
          1  physical reads
          0  redo size
       1444  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
三. 索引全扫描(index full scan ) 索引快速扫描(index fast full scan)
索引全扫描(index full scan )
与全表扫描对应,也有相应的全Oracle索引扫描。在某些情况下,可能进行全Oracle索引扫描而不是范围扫描,需要注意的是全Oracle索引扫描只在CBO模式下才有效。 CBO根据统计数值得知进行全Oracle索引扫描比进行全表扫描更有效时,才进行全Oracle索引扫描,而且此时查询出的数据都必须从索引中可以直接得到。
例子:
SQL> create table t3 as select * from dba_objects where object_id is not null;
表已创建。
SQL> alter table t3 modify(object_id not null);
表已更改。
SQL> create index index_t3 on t3(object_id);
索引已创建。
SQL> set autotrace trraceonly;
SQL> select /*+index(t index_t3) */ object_id from t3 t;
已选择114164行。
执行计划
----------------------------------------------------------
Plan hash value: 3077935993

-----------------------------------------------------------------------------
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |          |   114K|  1451K|   270   (1)| 00:00:04 |
|   1 |  INDEX FULL SCAN | INDEX_T3 |   114K|  1451K|   270   (1)| 00:00:04 |
-----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

统计信息
----------------------------------------------------------
          5  recursive calls
          0  db block gets
       7916  consistent gets
          0  physical reads
          0  redo size
    1663703  bytes sent via SQL*Net to client
      84126  bytes received via SQL*Net from client
       7612  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     114164  rows processed
     
索引快速扫描(index fast full scan)
扫描索引中的所有的数据块,与 index full scan很类似,在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。

SQL> select object_id from t3;

已选择114164行。

执行计划
----------------------------------------------------------
Plan hash value: 448706225

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

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

|   0 | SELECT STATEMENT     |          |   114K|  1451K|    74   (0)| 00:00:01
|   1 |  INDEX FAST FULL SCAN| INDEX_T3 |   114K|  1451K|    74   (0)| 00:00:01
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

统计信息
----------------------------------------------------------
         19  recursive calls
          0  db block gets
       7931  consistent gets
        253  physical reads
          0  redo size
    1663703  bytes sent via SQL*Net to client
      84126  bytes received via SQL*Net from client
       7612  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     114164  rows processed

index full scan的时候oracle定位到索引的root block,然后到branch block(如果有的话),再定位到第一个leaf block, 然后根据leaf block的双向链表顺序读取。它所读取的块都是有顺序的,也是经过排序的。
index fast full scan则不同,它是从段头开始,读取包含位图块,root block,所有的branch block, leaf block,读取的顺序完全有物理存储位置决定,并采取多块读,每次读取db_file_multiblock_read_count个块。
使用这两种索引扫描需要表的索引字段至少有一个是not null限制。快速全索引扫描比普通索引扫描速度快是因为快速索引扫描能够多块读取,并且能并行处理。
四. 索引跳跃扫描(INDEX SKIP SCAN)
索引跳跃扫描主要发生在对复合索引的列进行过滤时,没有写上先导列,并且先导列中的重复值较多,而非先导列中的重复数据较少。
SQL> create table t5 as select t.*,rownum id from user_tables t;
表已创建。
SQL> create index index_t5 on t5(table_name,id) ;
索引已创建。
SQL> begin
  2  dbms_stats.gather_table_stats(ownname =>'BOC_RWA3' ,tabname => 'T5' );
  3  end;
  4  /

PL/SQL 过程已成功完成。
当在where 条件中出现前导列时为INDEX RANGE SCAN 
select * from t5 t where table_name = 'T1';
执行计划
----------------------------------------------------------
Plan hash value: 1915796132

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

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

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

|   0 | SELECT STATEMENT            |          |     1 |   214 |     3   (0)| 00

|   1 |  TABLE ACCESS BY INDEX ROWID| T5       |     1 |   214 |     3   (0)| 00

|*  2 |   INDEX RANGE SCAN          | INDEX_T5 |     1 |       |     2   (0)| 00

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

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("TABLE_NAME"='T1')

统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
       4144  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
当在where 条件中出现非前导列时为INDEX SKIP SCAN
SQL> select * from t5 t where id = 10;
执行计划
----------------------------------------------------------
Plan hash value: 2396816619

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

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

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

|   0 | SELECT STATEMENT            |          |     1 |   214 |    11   (0)| 00

|   1 |  TABLE ACCESS BY INDEX ROWID| T5       |     1 |   214 |    11   (0)| 00

|*  2 |   INDEX SKIP SCAN           | INDEX_T5 |     1 |       |    10   (0)| 00

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

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("ID"=10)
       filter("ID"=10)

统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         13  consistent gets
          0  physical reads
          0  redo size
       4153  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

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

禁用skip scan:

alter system set “_optimizer_skip_scan_enabled” = false scope=spfile;

Oracle 索引扫描的4种类型的更多相关文章

  1. Oracle 索引扫描的五种类型

    之前在讨论CBO和RBO的时候提到了索引扫描的几种类型. Oracle Optimizer CBO RBO http://blog.csdn.net/tianlesoftware/archive/20 ...

  2. Oracle 索引扫描的几种情况

    index range scan(索引范围扫描): 1.对于unique index来说,如果where 条件后面出现了<,> ,between ...and...的时候,那么就可能执行i ...

  3. Oracle索引扫描

    Oracle索引扫描:先通过index查找到索引的值,并根据索引的值对应的rowid值(对于非唯一索引可能返回多个rowid值)直接从表中得到具体的数据.一个rowid唯一的表示一行数据,该行对应的数 ...

  4. Oracle索引扫描算法

    SQL> create table t as select * from dba_objects; Table created. SQL> create index idx_t on t( ...

  5. oracle 索引扫描类型的分类与构造

    1. INDEX RANGE SCAN--请记住这个INDEX RANGE SCAN扫描方式drop table t purge;create table t as select * from dba ...

  6. Oracle索引梳理系列(八)- 索引扫描类型及分析(高效索引必备知识)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  7. oracle 基础知识(十四)----索引扫描

    (1)索引唯一扫描(index unique scan) 通过唯一索引查找一个数值经常返回单个ROWID.如果该唯一索引有多个列组成(即组合索引),则至少要有组合索引的引导列参与到该查询中,如创建一个 ...

  8. 关于ORACLE索引的几种扫描方式

    ------------恢复内容开始------------ ------------恢复内容开始------------ 一条sql执行的效率因执行计划的差异而影响,经常说这条sql走索引了,那条s ...

  9. Oracle 表的访问方式(2)-----索引扫描

    索引扫描(Index scan) 我们先通过index查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这种查找方式称为索引扫描或索引 ...

随机推荐

  1. Myeclipse6.5配置反编译插件

    PS:jad.exe位置与Myeclipse6.5安装目录平行

  2. Headroom.js

    下载 Development (3.7kB) Production (1.7kB) Headroom.js 是什么? Headroom.js 是一个轻量级.高性能的JS小工具(不依赖任何工具库!),它 ...

  3. tr转换或删除字符

    字符处理命令:tr —— 转换或删除字符 逐个字符处理而不是处理单词的tr [OPTION]... SET1 [SET2]    -d: 删除出现在字符集中的所有字符 tr ab AB

  4. IOS 排序算法

    /** * @brief 冒泡排序法 * * @param arr 需要排序的数组 */ -(void)BubbleSort:(NSMutableArray *)arr { // 取第一个与其邻接的对 ...

  5. 怎样查询SCI和EI检索号

    为了年终考核,花了一个早上才搞清楚,里面有非常多小问题.以下具体说明具体过程: SCI检索号 1.进入图书馆主页: 2.选择"电子数据库": 3.选择外文数据库中的"We ...

  6. 从决策树学习谈到贝叶斯分类算法、EM、HMM

    从决策树学习谈到贝叶斯分类算法.EM.HMM                (Machine Learning & Recommend Search交流新群:172114338) 引言 log ...

  7. iOS 苹果app提交 ITC.apps.validation.prerelease_build_missing

    提示这信息,由于没有选择包文件, 在提交页面以下bulid的区域, 加入你的app就可以 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxpbmNleG ...

  8. android 更改USB显示名称

    能力 kernel\drivers\usb\gadget\Android.c 在这个例子中,下列的变化 #define PRODUCT_STRING "Sergeycao" 版权声 ...

  9. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设 ...

  10. Unity 安卓Jar包的小错误

    好久没写博客了,也就意味着好久没有学习了,近几天在搞Unity接入有米的SDk遇到了一点小错误,今天早上解决了,和大家分享下! 1,我们的目的是在在U3D中调用Android产生的Jar包,首先在Ec ...