版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载。转载时,请在文章明显位置注明原文链接。若在未经作者同意的情况下,将本文内容用于商业用途,将保留追究其法律责任的权利。如果有问题,请以邮箱方式联系作者(793113046@qq.com)。


理解oracle索引扫描类型的特点以及具体触发的条件,对于通过合理地使用索引,进行sql优化至关重要(例如组合索引的引导列的选择问题)

在总结索引扫描类型前,需要再次强调关于索引特点的几个关键点:

  • 对于单一列建立的索引,既单一列索引,b-tree中不保存索引列的null值信息
  • 对于多个列建立的索引,既组合列索引,b-tree中会连同其他非null值列,保留该列null值记录;对于一条记录中,组合索引全部列都是null值,组合索引中不会记录(从之前的实验看,此时的执行计划是全表扫描)
  • 创建主键约束以及唯一键约束,或自动创建唯一索引
  • create index创建的索引属于普通索引(非唯一索引)
  • create unique index创建的索引属于唯一索引

其他的一些特点,可参阅前面的几篇总结。

此外,为避免概念的混淆,再次说明一下:“索引类型”主要探讨的是索引的几种类别的问题,而“索引扫描类型”主要探讨的是索引扫描的几种具体实现方法的问题。

1、索引扫描类型概述

Oracle提供了五种索引扫描类型,根据具体索引类型、数据分布、约束条件以及where限制的不同进行选择:

  • 索引唯一扫描(index unique scan)
  • 索引范围扫描(index range scan)
  • 索引跳跃扫描(index skip scan)
  • 索引全扫描(index full scan)
  • 索引快速扫描(index fast full scan)

2、索引唯一扫描(index unique scan)

索引唯一扫描,仅仅针对唯一索引的扫描,且仅适用于等值(=)条件的查询。从结果集看,至多返回一条记录。

具体情况分析:

  • 对于单一列建立的索引(单一索引),当索引属于唯一索引,在检索条件中,使用该索引进行检索,且检索值不是null时,会使用“索引唯一扫描”
  • 对于单一列建立的索引(单一索引),当索引属于唯一索引,在检索条件中,使用该索引进行检索,且检索值等于null时,会使用“全表扫描”
  • 对于多个列建立的索引(组合索引),当索引属于唯一索引,且检索条件中,使用该组合索引进行检索,且检索列使用组合索引涉及的所有列时,会使用“索引唯一扫描”

需要注意:

  • 对于组合索引,若其中涉及的部分列或则所有列,在同一条记录上存在null值。当使用完整的组合索引列作为检索条件,且使用该null值进行该条记录的检索时,不会使用“索引唯一扫描”

示例:

  1. --创建唯一索引
    Yumiko@Sunny >create unique index ind_test_normal on test_normal(empno,ENAME,SAL);
  2. Index created.
  3.  
  4.  
  5. Yumiko@Sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME,UNIQUENESS from user_indexes where TABLE_NAME='TEST_NORMAL';
  6.  
  7. INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
  8. ------------------------- --------------------------- --------------- ---------
  9. IND_TEST_NORMAL NORMAL TEST_NORMAL UNIQUE
  10.  
  11. --查询记录并查看执行计划
  12. Yumiko@Sunny >select * from TEST_NORMAL where empno=7369 and ENAME='SMITH' and sal=800;
  13.  
  14. EMPNO ENAME JOB SAL
  15. ---------- ---------- --------- ----------
  16. 7369 SMITH CLERK 800
  17.  
  18. Execution Plan
  19. ----------------------------------------------------------
  20. Plan hash value: 1399315988
  21. ------------------------------------------------------------------------------------------
  22. | Id | Operation | Name | Rows | Bytes|Cost (%CPU)| Time |
  23. ------------------------------------------------------------------------------------------
  24. | 0 | SELECT STATEMENT | | 1| 39| 1 (0)| 00:00:01|
  25. | 1 | TABLE ACCESS BY INDEX ROWID| TEST_NORMAL | 1| 39| 1 (0)| 00:00:01|
  26. |* 2 | INDEX UNIQUE SCAN | IND_TEST_NORMAL| 1| | 0 (0)| 00:00:01|
  27. ------------------------------------------------------------------------------------------
  28. Predicate Information (identified by operation id):
  29. ---------------------------------------------------
  30. 2 - access("EMPNO"=7369 AND "ENAME"='SMITH' AND "SAL"=800)
  31.  
  32. Statistics
  33. ----------------------------------------------------------
  34. 0 recursive calls
  35. 0 db block gets
  36. 2 consistent gets
  37. 16 physical reads
  38. 0 redo size
  39. 581 bytes sent via SQL*Net to client
  40. 458 bytes received via SQL*Net from client
  41. 1 SQL*Net roundtrips to/from client
  42. 0 sorts (memory)
  43. 0 sorts (disk)
  44. 1 rows processed

3、索引范围扫描(index range scan)

索引范围扫描,不仅可以针对唯一索引,也可以针对非唯一索引。从结果集看,可以是一条记录,也可以是多条记录。

具体情况分析:

  • 对于单一列建立的索引(单一索引),当索引属于唯一索引,在检索条件中,使用该索引进行检索,且使用范围的操作符(>,<,>=,<=,between),会使用“索引范围扫描”。
  • 对于单一列建立的索引(单一索引),当索引属于非唯一索引,在检索条件中,使用该索引进行检索,且检索值不是null值,会使用“索引范围扫描”。
  • 对于多个列建立的索引(组合索引),当索引属于唯一索引,在检索条件中,使用该索引进行检索,且检索列使用组合索引涉及的部分列,但必须存在组合索引的引导列(创建组合索引时指定的第一列)时,会使用“索引范围扫描”。
  • 对于多个列建立的索引(组合索引),当索引属于非唯一索引,在检索条件中,使用该索引进行检索,检索列涉及组合索引的部分列或者全部列,但必须存在组合索引的引导列(创建组合索引时指定的第一列)时,会使用“索引范围扫描”。

需要注意:

  • 对于组合索引,当一条记录的引导列存在null值,当检索条件中,针对该条记录,仅使用该引导列进行检索时,不会使用“索引范围扫描”。
  • 对于组合索引,当一条记录的引导列存在null值,当检索条件中,针对该条记录,在使用该引导列进行检索的同时,使用组合索引的其他列且这些列针对该条记录的列值不是null值,一并进行检索,会使用“索引范围扫描”。

示例:

  1. --创建普通索引
    Yumiko@Sunny >create index ind_test_normal on test_normal(empno,ENAME,SAL);
  2. Index created.
  3.  
  4. --验证普通索引创建情况,确认为非唯一索引
  5. Yumiko@Sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME,UNIQUENESS from user_indexes where TABLE_NAME='TEST_NORMAL';
  6.  
  7. INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
  8. ------------------------- --------------------------- --------------- ---------
  9. IND_TEST_NORMAL NORMAL TEST_NORMAL NONUNIQUE
  10.  
  11. --查询记录并观察执行计划,此时扫描类型为index range scan
  12. Yumiko@Sunny >select * from TEST_NORMAL where empno=7369 and ENAME='SMITH' and sal=800;
  13.  
  14. EMPNO ENAME JOB SAL
  15. ---------- ---------- --------- ----------
  16. 7369 SMITH CLERK 800
  17.  
  18. Execution Plan
  19. -----------------------------------------------
  20. Plan hash value: 67814702
  21. ---------------------------------------------------------------------------------------------
  22. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  23. ---------------------------------------------------------------------------------------------
  24. | 0 | SELECT STATEMENT | | 1 | 18 | 2 (0)| 00:00:01|
  25. | 1 | TABLE ACCESS BY INDEX ROWID| TEST_NORMAL | 1 | 18 | 2 (0)| 00:00:01|
  26. |* 2 | INDEX RANGE SCAN | IND_TEST_NORMAL| 1 | | 1 (0)| 00:00:01|
  27. ---------------------------------------------------------------------------------------------
  28. Predicate Information (identified by operation id):
  29. ---------------------------------------------------
  30. 2 - access("EMPNO"=7369 AND "ENAME"='SMITH' AND "SAL"=800)
  31.  
  32. Statistics
  33. ----------------------------------------------------------
  34. 0 recursive calls
  35. 0 db block gets
  36. 3 consistent gets
  37. 16 physical reads
  38. 0 redo size
  39. 717 bytes sent via SQL*Net to client
  40. 469 bytes received via SQL*Net from client
  41. 2 SQL*Net roundtrips to/from client
  42. 0 sorts (memory)
  43. 0 sorts (disk)
  44. 1 rows processed

4、索引跳跃扫描(index skip scan)

该索引扫描方式主要发生在组合索引上,且组合索引的引导列未被指定在检索条件中的情况下发生。
在组合索引中,无论该索引是否为唯一索引。当引导列未被指定在检索条件的情况下,可能会发生“索引跳跃扫描”

以下黄色字体内容摘引自http://book.51cto.com/art/201312/422441.htm

对于组合索引,在无前导列的情况下还能使用索引,是因为Oracle帮我们对该索引的前导列的所有distinct值做了遍历。
所谓的对目标索引的所有distinct值做遍历,其实际含义相当于对原目标SQL做等价改写(即把要用的目标索引的所有前导列的distinct值都加进来)。

例如:create index idx_employee on employee(gender,employee_id),表数据量10000行,其中gender列只有“M”跟“F”值。
当执行select * from employee where employee_id = 100时,相当于执行了等价改写,改写为:
select * from employee where gender = 'F' and employee_id = 100
union all
select * from employee where gender = 'M' and employee_id = 100;

因此,Oracle中的索引跳跃式扫描仅仅适用于那些目标索引前导列的distinct值数量较少、后续非前导列的可选择性又非常好的情形,因为索引跳跃式扫描的执行效率一定会随着目标索引前导列的distinct值数量的递增而递减。否则将执行全表扫描。

示例:

  1. --查询测试表的总数据量
    --该表总数据为22928
    Yumiko@Sunny >select count(*) from test;
  2.  
  3. COUNT(*)
  4. ----------
  5. 22928
  6.  
  7. --查询测试表中owner列的列值数据分布情况
    --从查询结果看,对于owner列,在22928行的数据中,只分布了3个不同的列值,数据数值的分布情况较为集中
  8. Yumiko@Sunny >select count(distinct owner) from test;
  9.  
  10. COUNT(DISTINCTOWNER)
  11. --------------------
  12. 3
  13.  
  14. --查询测试表中object_id列的数值分布情况
    --从查询结果看,对于object_id列,在22928行的数据中,分布了22912个不同的数值,该列整体的数值分布情况较为零散
  15. Yumiko@Sunny >select count(distinct object_id) from test;
  16.  
  17. COUNT(DISTINCTOBJECT_ID)
  18. ------------------------
  19. 22912
  20.  
  21. Yumiko@Sunny >desc test
  22. Name Null? Type
  23. ----------------------------------------------------------------------
  24. OWNER VARCHAR2(30)
  25. OBJECT_NAME VARCHAR2(128)
  26. SUBOBJECT_NAME VARCHAR2(30)
  27. OBJECT_ID NUMBER
  28. DATA_OBJECT_ID NUMBER
  29. OBJECT_TYPE VARCHAR2(19)
  30. CREATED DATE
  31. LAST_DDL_TIME DATE
  32. TIMESTAMP VARCHAR2(19)
  33. STATUS VARCHAR2(7)
  34. TEMPORARY VARCHAR2(1)
  35. GENERATED VARCHAR2(1)
  36. SECONDARY VARCHAR2(1)
  37.  
  38. --以数值较为集中的owner作为组合索引的引导列,创建普通索引
  39. Yumiko@Sunny >create index test on test(owner,OBJECT_ID);
  40. Index created.
  41.  
  42. Yumiko@Sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME,UNIQUENESS from user_indexes where TABLE_NAME='TEST';
  43.  
  44. INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
  45. ------------------------- ------------------- --------------- ---------
  46. TEST NORMAL TEST NONUNIQUE
  47.  
  48. --收集测试表最新的统计信息
  49. Yumiko@Sunny >analyze table test compute statistics for table for all columns for all indexes;
  50. Table analyzed.
  51.  
  52. --清空buffer cache缓冲池,保证无测试表的数据块存在在内存中,防止影响到测试结果
  53. Yumiko@Sunny >alter system flush buffer_cache;
  54. System altered.
  55.  
  56. --使用之前创建的组合索引,以组合索引非引导作为条件查询列进行条件查询
    --从执行计划看,oracle用到了索引扫描,而且采用index skip scan的方式进行扫描
  57. Yumiko@Sunny >select * from test where object_id=3;
  58.  
  59. Execution Plan
  60. ----------------------------------------------------------
  61. Plan hash value: 2389257771
  62. ----------------------------------------------------------------------------------
  63. | Id | Operation | Name | Rows | Bytes| Cost (%CPU)| Time |
  64. ----------------------------------------------------------------------------------
  65. | 0 | SELECT STATEMENT | | 1 | 86| 5 (0)| 00:00:01|
  66. | 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 86| 5 (0)| 00:00:01|
  67. |* 2 | INDEX SKIP SCAN | TEST | 1 | | 4 (0)| 00:00:01|
  68. ----------------------------------------------------------------------------------
  69. Predicate Information (identified by operation id):
  70. ---------------------------------------------------
  71. 2 - access("OBJECT_ID"=3)
  72. filter("OBJECT_ID"=3)
  73.  
  74. Statistics
  75. ----------------------------------------------------------
  76. 0 recursive calls
  77. 0 db block gets
  78. 6 consistent gets
  79. 24 physical reads
  80. 0 redo size
  81. 1402 bytes sent via SQL*Net to client
  82. 469 bytes received via SQL*Net from client
  83. 2 SQL*Net roundtrips to/from client
  84. 0 sorts (memory)
  85. 0 sorts (disk)
  86. 1 rows processed
  87.  
  88. --删除之前的索引
  89. Yumiko@Sunny >drop index test;
  90. Index dropped.
  91.  
  92.  
  93. --以数值分布较为零散的object_id列作为引导列,再次创建普通索引
  94. Yumiko@Sunny >create index test on test(OBJECT_ID,owner);
  95. Index created.
  96.  
  97. --收集测试表最新的统计信息
  98. Yumiko@Sunny >analyze table test compute statistics for table for all columns for all indexes;
  99. Table analyzed.
  100.  
  101. --清空buffer cache缓冲池,避免影响数据测试
  102. Yumiko@Sunny >alter system flush buffer_cache;
  103. System altered.
  104.  
  105. --使用上面刚刚创建的组合索引的非引导列owner作为条件查询列进行查询操作
    --从执行计划看,此次oracle未选择走索引扫描,而是采用了全表扫描的方式
    --到此,印证了之前对于index skip scan方式选择的说法
  106. Yumiko@Sunny >select * from test where owner='BI';
  107. 8 rows selected.
  108.  
  109. Execution Plan
  110. ----------------------------------------------------------
  111. Plan hash value: 1357081020
  112. ------------------------------------------------------------------------
  113. | Id | Operation | Name | Rows | Bytes| Cost (%CPU)| Time |
  114. ------------------------------------------------------------------------
  115. | 0 | SELECT STATEMENT | | 8 | 688| 74 (2)| 00:00:01|
  116. |* 1 | TABLE ACCESS FULL| TEST | 8 | 688| 74 (2)| 00:00:01|
  117. ------------------------------------------------------------------------
  118. Predicate Information (identified by operation id):
  119. ---------------------------------------------------
  120. 1 - filter("OWNER"='BI')
  121.  
  122. Statistics
  123. ----------------------------------------------------------
  124. 1 recursive calls
  125. 0 db block gets
  126. 318 consistent gets
  127. 315 physical reads
  128. 0 redo size
  129. 1583 bytes sent via SQL*Net to client
  130. 469 bytes received via SQL*Net from client
  131. 2 SQL*Net roundtrips to/from client
  132. 0 sorts (memory)
  133. 0 sorts (disk)
  134. 8 rows processed

5、索引全扫描(index full scan)

对于索引全扫描,就是使用目标索引进行索引扫描时,会扫描所有索引叶块的所有索引行。

对于索引全扫描,只适用于CBO。

对于索引全扫描,使用单块读取的方式,有序读取索引块。

对于索引全扫描,从结果集看,结果全部源于索引块,而且由于已经按照索引键值顺序排序,因此不需要单独排序

对于索引全扫描,会话会产生db file sequential reads事件。

具体情况分析:

  • 对于单一列建立的索引(单一索引),当该索引列有非空约束时,在具体检索中只检索该列全部数据,会使用“索引全扫描”。
  • 对于单一列建立的索引(单一索引),当该索引列无非空约束时,在具体检索中只检索该列全部数据,且是对该列的统计(count)或者非空条件查询(is not null),会使用“索引全扫描”。
  • 对于单一列建立的索引(单一索引),当该索引列无非空约束时,在具体检索中只检索该列全部数据,且是对该列的常规查询,不会使用“索引全扫描”。(这是因为对于oracle索引,对于列中存在的null值不记录在b-tree索引中)
  • 对于多个列建立的索引(组合索引),当该索引列有非空约束时,在具体检索中只检索组合索引中涉及的全部列或者部分列的全部数据,会使用“索引全扫描”。
  • 对于多个列建立的索引(组合索引),当该索引列无非空约束时,在具体检索中只检索组合索引中涉及的全部列或者部分列的全部数据,且是对这些相关列的统计(count)或者非空条件查询(is not null),会使用“索引全扫描”。
  • 对于多个列建立的索引(组合索引),当该索引列无非空约束时,在具体检索中只检索组合索引中涉及的全部列或者部分列的全部数据,且是对该列的常规查询,不会使用“索引全扫描”。

示例:

  1. --为测试表TEST_NORMALempno列添加非空约束
    Yumiko@Sunny >alter table TEST_NORMAL modify(empno not null);
  2. Table altered.
  3.  
  4. --以empno列以及ename列作为组合,创建普通索引
  5. Yumiko@Sunny >create index TEST_NORMAL_ind on TEST_NORMAL(empno,ename);
  6. Index created.
  7.  
  8. --查询上面组合索引涉及的ename列,该列不存在非空约束
    --从执行计划看,oracle选择了index full scan的索引扫描方式,且结果集仅仅来源于索引块(没有根据rowid返回数据集的记录,说明无访问数据块)
  9. Yumiko@Sunny >select ename from TEST_NORMAL;
  10. 14 rows selected.
  11.  
  12. Execution Plan
  13. ----------------------------------------------------------
  14. Plan hash value: 2425626010
  15. ------------------------------------------------------------------------------------
  16. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  17. ------------------------------------------------------------------------------------
  18. | 0 | SELECT STATEMENT | | 14 | 70 | 1 (0)| 00:00:01 |
  19. | 1 | INDEX FULL SCAN | TEST_NORMAL_IND | 14 | 70 | 1 (0)| 00:00:01 |
  20. ------------------------------------------------------------------------------------
  21. Statistics
  22. ----------------------------------------------------------
  23. 0 recursive calls
  24. 0 db block gets
  25. 2 consistent gets
  26. 8 physical reads
  27. 0 redo size
  28. 705 bytes sent via SQL*Net to client
  29. 469 bytes received via SQL*Net from client
  30. 2 SQL*Net roundtrips to/from client
  31. 0 sorts (memory)
  32. 0 sorts (disk)
  33. 14 rows processed

6、索引快速扫描(index fast full scan)

对于索引快速扫描,就是使用目标索引进行索引扫描时,会扫描所有索引叶块的所有索引行。

对于索引快速扫描,只适用于CBO。

对于索引快速扫描,使用多块读取的方式,读取索引块。(这种方式相较于索引全扫描,获取数据的效率更高)

对于索引快速扫描,从结果集看,结果全部源于索引块,但数据结果不一定有序。

对于索引快速扫描,会话会产生db file scattered reads事件。

具体情况分析:

参阅上面的索引全扫描,两者所谓的同宗,只是不同的需求(对于结果的响应速度或是数据序列,当然CBO优化器也会进行内部的计算评估选取最优执行路径),产生的不同的执行结果,下面的示例会展示

示例:

  1. --查询测试表的数据量,显示此表有22928行数据
    Yumiko@Sunny >select count(*) from test;
  2.  
  3. COUNT(*)
  4. ----------
  5. 22928
  6.  
  7. --确认数据列中不含非空约束
  8. Yumiko@Sunny >desc test
  9. Name Null? Type
  10. --------------------------------------------------------------------------------
  11. OWNER VARCHAR2(30)
  12. OBJECT_NAME VARCHAR2(128)
  13. SUBOBJECT_NAME VARCHAR2(30)
  14. OBJECT_ID NUMBER
  15. DATA_OBJECT_ID NUMBER
  16. OBJECT_TYPE VARCHAR2(19)
  17. CREATED DATE
  18. LAST_DDL_TIME DATE
  19. TIMESTAMP VARCHAR2(19)
  20. STATUS VARCHAR2(7)
  21. TEMPORARY VARCHAR2(1)
  22. GENERATED VARCHAR2(1)
  23. SECONDARY VARCHAR2(1)
  24.  
  25. --针对object_id列,创建普通索引
  26. Yumiko@Sunny >create index test on test(object_id);
  27. Index created.
  28.  
  29. --确认上面创建的索引为非唯一索引
  30. Yumiko@Sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME,UNIQUENESS from user_indexes where TABLE_NAME='TEST';
  31.  
  32. INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
  33. -------------------------------------------------------------------------
  34. TEST NORMAL TEST NONUNIQUE
  35.  
  36. --清空buffer_cache缓冲池数据,防止造成测试的影响
  37. Yumiko@Sunny >alter system flush buffer_cache;
  38. System altered.
  39.  
  40. --清空shared pool缓冲池数据,防止对测试造成影响
  41. Yumiko@Sunny >alter system flush shared_pool;
  42. System altered.
  43.  
  44. --收集测试表最新的统计信息
  45. Yumiko@Sunny >analyze table test compute statistics for table for all columns for all indexes;
  46. Table analyzed.
  47.  
  48. --打开会话追踪,仅查看执行计划
  49. Yumiko@Sunny >set autotrace trace
  50.  
  51. --查询索引列object,同时使用is not null作为查询条件。
    --由于b-tree索引中不记录null值信息,而且该列不存在非空约束,通过not null条件指定,让oracle不必考虑null值。
    --从执行计划看,由于读取的数据量很大且不用排序,oracle选择了更快的多块读方式的index fast full scan,尽快获取数据。
    --同样的,此时未出现access by index rowid的情况,说明未查询数据块,仅仅查询了索引块。
  52. Yumiko@Sunny >select object_id from test where object_id is not null;
  53. 22928 rows selected.
  54.  
  55. Execution Plan
  56. ----------------------------------------------------------
  57. Plan hash value: 1645531115
  58. -----------------------------------------------------------------------------
  59. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  60. -----------------------------------------------------------------------------
  61. | 0 | SELECT STATEMENT | | 23290 | 295K| 14 (0)| 00:00:01 |
  62. |* 1 | INDEX FAST FULL SCAN| TEST | 23290 | 295K| 14 (0)| 00:00:01 |
  63. -----------------------------------------------------------------------------
  64.  
  65. Predicate Information (identified by operation id):
  66. ---------------------------------------------------
  67. 1 - filter("OBJECT_ID" IS NOT NULL)
  68.  
  69. Statistics
  70. ----------------------------------------------------------
  71. 0 recursive calls
  72. 0 db block gets
  73. 1582 consistent gets
  74. 53 physical reads
  75. 0 redo size
  76. 502642 bytes sent via SQL*Net to client
  77. 17277 bytes received via SQL*Net from client
  78. 1530 SQL*Net roundtrips to/from client
  79. 0 sorts (memory)
  80. 0 sorts (disk)
  81. 22928 rows processed
  82.  
  83. --修改上面的查询,增加排序操作。
    --从执行计划看,由于此次增加了排序操作,oracle选择了偏向有序读取的index full scan的方式进行扫描。
    --同样的,此次未查询数据块(不存在access by index rowid)。
  84. Yumiko@Sunny >select object_id from test where object_id is not null order by object_id;
  85. 22928 rows selected.
  86.  
  87. Execution Plan
  88. ----------------------------------------------------------
  89. Plan hash value: 3883652822
  90. -------------------------------------------------------------------------
  91. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  92. -------------------------------------------------------------------------
  93. | 0 | SELECT STATEMENT | | 23290 | 295K| 60 (2)| 00:00:01 |
  94. |* 1 | INDEX FULL SCAN | TEST | 23290 | 295K| 60 (2)| 00:00:01 |
  95. -------------------------------------------------------------------------
  96. Predicate Information (identified by operation id):
  97. ---------------------------------------------------
  98. 1 - filter("OBJECT_ID" IS NOT NULL)
  99.  
  100. Statistics
  101. ----------------------------------------------------------
  102. 0 recursive calls
  103. 0 db block gets
  104. 1578 consistent gets
  105. 64 physical reads
  106. 0 redo size
  107. 502642 bytes sent via SQL*Net to client
  108. 17277 bytes received via SQL*Net from client
  109. 1530 SQL*Net roundtrips to/from client
  110. 0 sorts (memory)
  111. 0 sorts (disk)
  112. 22928 rows processed
  113.  
  114. --再次修改查询,取消not null条件查询以及排序操作。
    --此时,对于没有非空约束的object_id列,增加了null值的可能性,而b-tree索引不保存null信息。
    --此次,oracle选择了全表扫描的方式。
  115. Yumiko@Sunny >select object_id from test;
  116. 22928 rows selected.
  117.  
  118. Execution Plan
  119. ----------------------------------------------------------
  120. Plan hash value: 1357081020
  121. --------------------------------------------------------------------------
  122. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  123. --------------------------------------------------------------------------
  124. | 0 | SELECT STATEMENT | | 22928 | 91712 | 74 (2)| 00:00:01 |
  125. | 1 | TABLE ACCESS FULL| TEST | 22928 | 91712 | 74 (2)| 00:00:01 |
  126. --------------------------------------------------------------------------
  127. Statistics
  128. ----------------------------------------------------------
  129. 1 recursive calls
  130. 0 db block gets
  131. 1830 consistent gets
  132. 315 physical reads
  133. 0 redo size
  134. 415626 bytes sent via SQL*Net to client
  135. 17277 bytes received via SQL*Net from client
  136. 1530 SQL*Net roundtrips to/from client
  137. 0 sorts (memory)
  138. 0 sorts (disk)
  139. 22928 rows processed

由于篇幅有限,关于索引扫描类型的总结到此为止。若存在内容上的遗漏,或者错误,欢迎各位指教。

Oracle索引梳理系列(八)- 索引扫描类型及分析(高效索引必备知识)的更多相关文章

  1. [独孤九剑]Oracle知识点梳理(八)常见Exception

    本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracl ...

  2. Oracle索引梳理系列(十)- 直方图使用技巧及analyze table操作对直方图统计的影响(谨慎使用)

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

  3. Oracle索引梳理系列(七)- Oracle唯一索引、普通索引及约束的关系

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

  4. Oracle索引梳理系列(五)- Oracle索引种类之表簇索引(cluster index)

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

  5. Oracle索引梳理系列(二)- Oracle索引种类及B树索引

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

  6. Oracle索引梳理系列(九)- 浅谈聚簇因子对索引使用的影响及优化方法

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

  7. Oracle索引梳理系列(六)- Oracle索引种类之函数索引

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

  8. Oracle索引梳理系列(一)- Oracle访问数据的方法

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

  9. Oracle索引梳理系列(四)- Oracle索引种类之位图索引

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

随机推荐

  1. 软件工程-构建之法 WordCount小程序 统计文件中字符串个数,单词个数,词频,行数

    一.前言 在之前写过一个词频统计的C语言课设,别人说你一个大三的怎么写C语言课程,我只想说我是先学习VB,VB是我编程语言的开始,然后接触到C语言及C++:再后来我是学习C++,然后反过来学习C语言, ...

  2. 加入一个线程:join

    在启动一个线程之后调用该线程的join()方法,会使该线程先执行,该线程执行完成后,再执行调用该线程的线程. 例如如下的任务: public class LiftOff extends Thread ...

  3. Objective-C 对象(内容根据iOS编程编写)

    开发iOS程序需要使用 Objective-C 语言和Cocoa Touch框架.Objective-C 源于 C 语言,是 C 语言的扩展. Cocoa Touch框架是一个Objective-C类 ...

  4. js树形控件—zTree使用总结

    0 zTree简介 树形控件的使用是应用开发过程中必不可少的.zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 0.0 ...

  5. Keil环境中建立带FreeRTOS的STM32L项目

    本文是网上转载,版权所有. Keil环境中建立带FreeRTOS的STM32L项目 1.先把source文件夹复制至project目录,然后在keil中添加RTOS文件,如图: 其中heap_2.c按 ...

  6. rsa互通密钥对生成及互通加解密(c#,java,php)

    摘要 在数据安全上rsa起着非常大的作用,特别是数据网络通讯的安全上.当异构系统在数据网络通讯上对安全性有所要求时,rsa将作为其中的一种选择,此时rsa的互通性就显得尤为重要了. 本文参考网络资料, ...

  7. QRCode

    这个星期, 领导要我总结项目中用到的一些技术, 然后交付文档. 嘿嘿, 奉命整理. 二维码, 相信很多项目中都会要求生成这个, 然后由手机端去扫描, 或存储一些详情信息, 或存储一条链接, 可以快捷访 ...

  8. HtmlHelper拓展实现CheckBoxList

    经过一番折腾(主要是SelectList这个类操作有些繁琐)实现了CheckBoxList,过程RadioList基本一样 拓展方法 public static MvcHtmlString Check ...

  9. C# foreach 中获取索引index的方法

    方法一: int i = 0; foreach (var item in arr) { i++; } 方法二: foreach (var item in arr) { int index = arr. ...

  10. WCF的Restful和TCP方式调用性能比较

    1. 实验背景关于WCF提供分布式访问服务,最常用的两种方式Restful方式和Tcp方式,在本地测试了一把.结果显示,还是Rest方式,在压力测试下,性能最佳.而且处于跨平台的考虑,和自动化测试方便 ...