Oracle ROWID 方式访问数据库

简介:     和ROWNUM一样,ROWID是一个伪列,即是一个非用户定义的列,而又实际存储于数据库之中。每一个表都有一个ROWID列,一个ROWID值用于唯一确定数据库表中的的一条记录。

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

-->查看表上rowid
scott@CNMMBO> select rowid,empno,ename from emp where deptno=20;

ROWID                   EMPNO ENAME
------------------ ---------- ----------
AAATTBAALAAAAuUAAA       7369 SMITH
AAATTBAALAAAAuUAAD       7566 JONES
AAATTBAALAAAAuUAAH       7788 SCOTT
AAATTBAALAAAAuUAAK       7876 ADAMS
AAATTBAALAAAAuUAAM       7902 FORD				

-->下面使用rowid来进行访
-->以下演示中忽略了物理读,仅考虑逻辑读的情形
scott@CNMMBO> set autot trace;
scott@CNMMBO> select empno,ename from emp where rowid='AAATTBAALAAAAuUAAA';

Execution Plan
----------------------------------------------------------
Plan hash value: 1116584662
-----------------------------------------------------------------------------------
| Id  | Operation                  | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |      |     1 |    22 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY USER ROWID| EMP  |     1 |    22 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1  recursive calls     
          0  db block gets
          1  consistent gets     
          0  physical reads

--此时执行计划中操作1为TABLE 
ACCESS BY USER ROWID,注意此时为USER ROWID,表明由用户直接调用产生
--统计信息中的consistent gets为1,即只需要根据rowid即可返回数据 

--使用多个rowid的情形
scott@CNMMBO> select empno,ename from emp where rowid in ('AAATTBAALAAAAuUAAA','AAATTBAALAAAAuUAAD');

Execution Plan
----------------------------------------------------------
Plan hash value: 1106538681
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    22 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR            |      |       |       |            |          |
|   2 |   TABLE ACCESS BY USER ROWID| EMP  |     1 |    22 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads

--上面的执行计划中出现了INLIST ITERATOR,即INLIST迭代,该操作说明其子操作多次重复时,会出现该操作。
--由于我们使用了in运算,且传递了2个rowid,故出现INLIST迭代操作
--迭代操作意味着条件中的对象列表一个接一个的迭代传递给子操作
--此时统计信息中的consistent gets为2,因为一个rowid一次逻辑运算

--下面来看看直接使用列来访问表的情形
scott@CNMMBO> select empno,ename from emp where empno=7369;

Execution Plan
----------------------------------------------------------
Plan hash value: 2949544139
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    10 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    10 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7369)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads

--在通过谓词访问表时,此执行计划中使用了INDEX UNIQUE SCAN扫描方式
--此时先实施INDEX UNIQUE SCAN,然后将该操作的结果传递给父操作TABLE ACCESS BY INDEX ROWID来定位记录
--此时也给出了谓词信息:2 - access("EMPNO"=7369)
--此时的逻辑读consistent gets的值是2,即一次读索引,一次通过rowid读表上的数据块

--下面来看看直接使用列且使用in访问多条记录的情形
scott@CNMMBO> select empno,ename from emp where empno in (7369,7566);

Execution Plan
----------------------------------------------------------
Plan hash value: 1899965127
---------------------------------------------------------------------------------------
| Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |        |     2 |    20 |     2   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR             |        |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMP    |     2 |    20 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | PK_EMP |     2 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("EMPNO"=7369 OR "EMPNO"=7566)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          5  consistent gets
          0  physical reads

--此时执行计划中的索引扫描方式变成了索引范围扫描INDEX RANGE SCAN
--由于存在in操作,因此此时在第2步也出现了迭代操作
--此处的逻辑读consistent gets的值是5 ?  为什么是 5 呢? 下面来分析看看

scott@CNMMBO> alter system flush shared_pool;

scott@CNMMBO> alter system flush buffer_cache;

scott@CNMMBO> set serveroutput off;
scott@CNMMBO> set autot off;
scott@CNMMBO> select /*+ gather_plan_statistics */ empno,ename from emp where empno in (7369,7566);

     EMPNO ENAME
---------- ----------
      7369 SMITH
      7566 JONES

scott@CNMMBO> select * from table(dbms_xplan.display_cursor(null,null,'iostats last'));

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
SQL_ID  373xnw8s521t4, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ empno,ename from emp where empno in (7369,7566)

Plan hash value: 1899965127
----------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name   | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
----------------------------------------------------------------------------------------------------------
|   1 |  INLIST ITERATOR             |        |      1 |        |      2 |00:00:00.01 |       5 |      2 |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMP    |      2 |      2 |      2 |00:00:00.01 |       5 |      2 |
|*  3 |    INDEX RANGE SCAN          | PK_EMP |      2 |      2 |      2 |00:00:00.01 |       3 |      1 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access(("EMPNO"=7369 OR "EMPNO"=7566))

--从上面的执行计划可知,2次索引扫描,2次rowid扫描,加上1次迭代,因此总的consistent gets为5。

--与此类似的使用基于rowid的update操作,其性能同样高于直接使用列来实现update操作,此处不再演示

--使用rowid删除重复记录的示例
DELETE FROM emp e                                                                     
WHERE  e.ROWID > (SELECT MIN( x.ROWID )     
                 FROM   emp x                                                       
                 WHERE  x.empno = e.empno);  

--Author: Robinson Cheng
--Blog :  http://blog.csdn.net/robinson_0612
                 
--总结:
    使用rowid访问数据时可以减少逻辑读的数量,因为一个rowid能唯一定位一条记录
    尽管rowid能极大程度的提高数据的访问效率,然而由于其不易识别性(为十六进制)在大量数据访问时并不易于使用 

更多参考

Oracle ROWID

NULL 值与索引(一)

NULL 值与索引(二)

SQL tuning 步骤

高效SQL语句必杀技

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

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

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

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

启用 AUTOTRACE 功能

函数使得索引列失效

Oracle 绑定变量窥探

Oracle 自适应共享游标              

 

目录
相关文章
|
11天前
|
DataWorks Oracle 关系型数据库
DataWorks操作报错合集之尝试从Oracle数据库同步数据到TDSQL的PG版本,并遇到了与RAW字段相关的语法错误,该怎么处理
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
29 0
|
2天前
|
存储 Oracle 关系型数据库
oracle 数据库 迁移 mysql数据库
将 Oracle 数据库迁移到 MySQL 是一项复杂的任务,因为这两种数据库管理系统具有不同的架构、语法和功能。
12 0
|
17天前
|
存储 Oracle 网络协议
Oracle 11gR2学习之二(创建数据库及OEM管理篇)
Oracle 11gR2学习之二(创建数据库及OEM管理篇)
|
21天前
|
Oracle 网络协议 关系型数据库
异地使用PLSQL远程连接访问Oracle数据库【内网穿透】
异地使用PLSQL远程连接访问Oracle数据库【内网穿透】
|
22天前
|
SQL Oracle 安全
Oracle数据库中的事务和锁
【4月更文挑战第19天】Oracle数据库的事务和锁是确保数据完整性和并发控制的核心机制。事务遵循ACID原则,保证操作的原子性、一致性、隔离性和持久性。通过COMMIT或ROLLBACK来管理事务更改。锁包括共享锁(读)、排他锁(写)、行级锁和表级锁,用于控制并发访问。自动锁机制在DML操作时生效,防止数据冲突。事务和锁共同维护数据库的稳定和安全。
|
22天前
|
存储 Oracle 关系型数据库
Oracle RAC:数据库集群的舞动乐章
【4月更文挑战第19天】Oracle RAC是Oracle提供的高可用性数据库解决方案,允许多个实例共享同一数据库,确保业务连续性和数据完整性。通过集群件和全局缓存服务实现服务器间的协调和通信。RAC提供高可用性,通过故障转移应对故障,同时提升性能,多个实例并行处理请求。作为数据管理员,理解RAC的架构和管理至关重要,以发挥其在数据管理中的最大价值。
|
22天前
|
监控 Oracle 安全
Oracle用户事件触发器:数据库世界的“福尔摩斯”
【4月更文挑战第19天】Oracle用户事件触发器是数据库中的监控机制,类似于“福尔摩斯”,在用户执行特定操作时自动触发。它们关注用户行为而非数据变化,可用于权限检查、安全监控、性能优化等。通过DDL语句创建,需注意逻辑清晰、条件合适及定期更新,以适应数据库变化和业务发展。掌握其使用能有效保障数据安全与稳定。
|
22天前
|
SQL 存储 Oracle
Oracle语句级触发器:数据库的“隐形哨兵”
【4月更文挑战第19天】Oracle语句级触发器是数据库中的自动执行程序,当特定事件(如INSERT、UPDATE、DELETE)发生时,会针对整个SQL语句触发。以新员工入职记录日志为例,创建语句级触发器可自动在操作后向日志表插入信息,减少手动工作并提高性能。虽然无法处理行级详细信息,但在处理大量数据时,相比行级触发器更高效。掌握触发器使用能提升数据管理效率和安全性。
|
22天前
|
Oracle 关系型数据库 数据库
Oracle示例模式Scott:数据库世界的“小导游”
【4月更文挑战第19天】Oracle的Scott模式是数据库学习的向导,提供操作性的环境,包含表(如EMP和DEPT)、视图和索引。通过它,学习者能掌握基本语法和操作,如创建表、插入数据和编写查询。它是通往Oracle数据库世界的起点,帮助新手奠定基础,开启数据库探索之旅。
|
22天前
|
存储 Oracle 关系型数据库
Oracle的模式与模式对象:数据库的“城市规划师”
【4月更文挑战第19天】在Oracle数据库中,模式是用户对象的集合,相当于数据库的城市规划,包含表、视图、索引等模式对象。模式对象是数据存储结构,如表用于存储数据,视图提供不同查看角度,索引加速数据定位。良好的模式与模式对象设计关乎数据效率、安全和稳定性。规划时需考虑业务需求、性能、安全和可扩展性,以构建高效数据库环境,支持企业业务发展。