Oracle ROWID 方式访问数据库

转自 http://blog.csdn.net/leshami/article/details/7474308

和ROWNUM一样,ROWID是一个伪列,即是一个非用户定义的列,而又实际存储于数据库之中。每一个表都有一个ROWID列,一个ROWID值用于
唯一确定数据库表中的的一条记录。因此通过ROWID 方式来访问数据也是 Oracle 数据库访问数据的实现方式之一。一般情况下,ROWID方式的
访问一定以索引访问或用户指定ROWID作为先决条件,因为所有的索引访问方式最终都会转换为通过ROWID来访问数据记录。(注:index full
scan 与index fast full scan
除外)由于Oracle ROWID能够直接定位一条记录,因此使用ROWID方式来访问数据,极大提高数据的访问效率。

  1. -->查看表上rowid  
  2. scott@CNMMBO> select rowid,empno,ename from emp where deptno=20;  
  3.   
  4. ROWID                   EMPNO ENAME  
  5. ------------------ ---------- ----------  
  6. AAATTBAALAAAAuUAAA       7369 SMITH  
  7. AAATTBAALAAAAuUAAD       7566 JONES  
  8. AAATTBAALAAAAuUAAH       7788 SCOTT  
  9. AAATTBAALAAAAuUAAK       7876 ADAMS  
  10. AAATTBAALAAAAuUAAM       7902 FORD                
  11.   
  12. -->下面使用rowid来进行访  
  13. -->以下演示中忽略了物理读,仅考虑逻辑读的情形  
  14. scott@CNMMBO> set autot trace;  
  15. scott@CNMMBO> select empno,ename from emp where rowid='AAATTBAALAAAAuUAAA';  
  16.   
  17. Execution Plan  
  18. ----------------------------------------------------------  
  19. Plan hash value: 1116584662  
  20. -----------------------------------------------------------------------------------  
  21. | Id  | Operation                  | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  22. -----------------------------------------------------------------------------------  
  23. |   0 | SELECT STATEMENT           |      |     1 |    22 |     1   (0)| 00:00:01 |  
  24. |   1 |  TABLE ACCESS BY USER ROWID| EMP  |     1 |    22 |     1   (0)| 00:00:01 |  
  25. -----------------------------------------------------------------------------------  
  26. Statistics  
  27. ----------------------------------------------------------  
  28.           1  recursive calls       
  29.           0  db block gets  
  30.           1  consistent gets       
  31.           0  physical reads  
  32.   
  33. --此时执行计划中操作1为TABLE   
  34. ACCESS BY USER ROWID,注意此时为USER ROWID,表明由用户直接调用产生  
  35. --统计信息中的consistent gets为1,即只需要根据rowid即可返回数据   
  36.   
  37. --使用多个rowid的情形  
  38. scott@CNMMBO> select empno,ename from emp where rowid in ('AAATTBAALAAAAuUAAA','AAATTBAALAAAAuUAAD');  
  39.   
  40. Execution Plan  
  41. ----------------------------------------------------------  
  42. Plan hash value: 1106538681  
  43. ------------------------------------------------------------------------------------  
  44. | Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  45. ------------------------------------------------------------------------------------  
  46. |   0 | SELECT STATEMENT            |      |     1 |    22 |     1   (0)| 00:00:01 |  
  47. |   1 |  INLIST ITERATOR            |      |       |       |            |          |  
  48. |   2 |   TABLE ACCESS BY USER ROWID| EMP  |     1 |    22 |     1   (0)| 00:00:01 |  
  49. ------------------------------------------------------------------------------------  
  50. Statistics  
  51. ----------------------------------------------------------  
  52.           1  recursive calls  
  53.           0  db block gets  
  54.           2  consistent gets  
  55.           0  physical reads  
  56.   
  57. --上面的执行计划中出现了INLIST ITERATOR,即INLIST迭代,该操作说明其子操作多次重复时,会出现该操作。  
  58. --由于我们使用了in运算,且传递了2个rowid,故出现INLIST迭代操作  
  59. --迭代操作意味着条件中的对象列表一个接一个的迭代传递给子操作  
  60. --此时统计信息中的consistent gets为2,因为一个rowid一次逻辑运算  
  61.   
  62. --下面来看看直接使用列来访问表的情形  
  63. scott@CNMMBO> select empno,ename from emp where empno=7369;  
  64.   
  65. Execution Plan  
  66. ----------------------------------------------------------  
  67. Plan hash value: 2949544139  
  68. --------------------------------------------------------------------------------------  
  69. | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  70. --------------------------------------------------------------------------------------  
  71. |   0 | SELECT STATEMENT            |        |     1 |    10 |     1   (0)| 00:00:01 |  
  72. |   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    10 |     1   (0)| 00:00:01 |  
  73. |*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |  
  74. --------------------------------------------------------------------------------------  
  75. Predicate Information (identified by operation id):  
  76. ---------------------------------------------------  
  77.    2 - access("EMPNO"=7369)  
  78. Statistics  
  79. ----------------------------------------------------------  
  80.           1  recursive calls  
  81.           0  db block gets  
  82.           2  consistent gets  
  83.           0  physical reads  
  84.   
  85. --在通过谓词访问表时,此执行计划中使用了INDEX UNIQUE SCAN扫描方式  
  86. --此时先实施INDEX UNIQUE SCAN,然后将该操作的结果传递给父操作TABLE ACCESS BY INDEX ROWID来定位记录  
  87. --此时也给出了谓词信息:2 - access("EMPNO"=7369)  
  88. --此时的逻辑读consistent gets的值是2,即一次读索引,一次通过rowid读表上的数据块  
  89.   
  90. --下面来看看直接使用列且使用in访问多条记录的情形  
  91. scott@CNMMBO> select empno,ename from emp where empno in (7369,7566);  
  92.   
  93. Execution Plan  
  94. ----------------------------------------------------------  
  95. Plan hash value: 1899965127  
  96. ---------------------------------------------------------------------------------------  
  97. | Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  98. ---------------------------------------------------------------------------------------  
  99. |   0 | SELECT STATEMENT             |        |     2 |    20 |     2   (0)| 00:00:01 |  
  100. |   1 |  INLIST ITERATOR             |        |       |       |            |          |  
  101. |   2 |   TABLE ACCESS BY INDEX ROWID| EMP    |     2 |    20 |     2   (0)| 00:00:01 |  
  102. |*  3 |    INDEX RANGE SCAN          | PK_EMP |     2 |       |     1   (0)| 00:00:01 |  
  103. ---------------------------------------------------------------------------------------  
  104. Predicate Information (identified by operation id):  
  105. ---------------------------------------------------  
  106.    3 - access("EMPNO"=7369 OR "EMPNO"=7566)  
  107. Statistics  
  108. ----------------------------------------------------------  
  109.           1  recursive calls  
  110.           0  db block gets  
  111.           5  consistent gets  
  112.           0  physical reads  
  113.   
  114. --此时执行计划中的索引扫描方式变成了索引范围扫描INDEX RANGE SCAN  
  115. --由于存在in操作,因此此时在第2步也出现了迭代操作  
  116. --此处的逻辑读consistent gets的值是5 ?  为什么是 5 呢? 下面来分析看看  
  117.   
  118. scott@CNMMBO> alter system flush shared_pool;  
  119.   
  120. scott@CNMMBO> alter system flush buffer_cache;  
  121.   
  122. scott@CNMMBO> set serveroutput off;  
  123. scott@CNMMBO> set autot off;  
  124. scott@CNMMBO> select /*+ gather_plan_statistics */ empno,ename from emp where empno in (7369,7566);  
  125.   
  126.      EMPNO ENAME  
  127. ---------- ----------  
  128.       7369 SMITH  
  129.       7566 JONES  
  130.   
  131. scott@CNMMBO> select * from table(dbms_xplan.display_cursor(null,null,'iostats last'));  
  132.   
  133. PLAN_TABLE_OUTPUT  
  134. ----------------------------------------------------------------------------  
  135. SQL_ID  373xnw8s521t4, child number 0  
  136. -------------------------------------  
  137. select /*+ gather_plan_statistics */ empno,ename from emp where empno in (7369,7566)  
  138.   
  139. Plan hash value: 1899965127  
  140. ----------------------------------------------------------------------------------------------------------  
  141. | Id  | Operation                    | Name   | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  
  142. ----------------------------------------------------------------------------------------------------------  
  143. |   1 |  INLIST ITERATOR             |        |      1 |        |      2 |00:00:00.01 |       5 |      2 |  
  144. |   2 |   TABLE ACCESS BY INDEX ROWID| EMP    |      2 |      2 |      2 |00:00:00.01 |       5 |      2 |  
  145. |*  3 |    INDEX RANGE SCAN          | PK_EMP |      2 |      2 |      2 |00:00:00.01 |       3 |      1 |  
  146. ----------------------------------------------------------------------------------------------------------  
  147. Predicate Information (identified by operation id):  
  148. ---------------------------------------------------  
  149.    3 - access(("EMPNO"=7369 OR "EMPNO"=7566))  
  150.   
  151. --从上面的执行计划可知,2次索引扫描,2次rowid扫描,加上1次迭代,因此总的consistent gets为5。  
  152.   
  153. --与此类似的使用基于rowid的update操作,其性能同样高于直接使用列来实现update操作,此处不再演示  
  154.   
  155. --使用rowid删除重复记录的示例  
  156. DELETE FROM emp e                                                                       
  157. WHERE  e.ROWID > (SELECT MIN( x.ROWID )       
  158.                  FROM   emp x                                                         
  159.                  WHERE  x.empno = e.empno);    
  160.   
  161. --Author: Robinson Cheng  
  162. --Blog :  http://blog.csdn.net/robinson_0612  
  163.                    
  164. --总结:  
  165.     使用rowid访问数据时可以减少逻辑读的数量,因为一个rowid能唯一定位一条记录  
  166.     尽管rowid能极大程度的提高数据的访问效率,然而由于其不易识别性(为十六进制)在大量数据访问时并不易于使用   

更多参考

Oracle ROWID

NULL 值与索引(一)

NULL 值与索引(二)

SQL tuning 步骤

 

高效SQL语句必杀技

父游标、子游标及共享游标

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

执行计划中各字段各模块描述

使用 EXPLAIN PLAN 获取SQL语句执行计划

启用 AUTOTRACE 功能

函数使得索引列失效

Oracle 绑定变量窥探

Oracle 自适应共享游标              

 

posted @ 2014-03-19 13:40  princessd8251  阅读(281)  评论(0编辑  收藏  举报