本文讨论的是关于oracle从8i开始引进object的概念后的rowid,即扩展(extended)的rowid:
1.rowid的介绍
先对rowid有个感官认识:
SQL> select ROWID from Bruce_test where rownum<2;
ROWID
------------------ ----------
AAABnlAAFAAAAAPAAA
ROWID的格式如下:
Object Segment      file            dbblock         
数据对象编号        文件编号        块编号           行编号
OOOOOO              FFF             BBBBBB           RRR
我们可以看出,从上面的rowid可以得知:
AAABnl 是数据对象编号
AAF是相关文件编号
AAAAAP是块编号
AAA 是行编号
怎么依据这些编号得到具体的十进制的编码值呢,这是经常遇到的问题。
这里需要明白rowid的是基于64位编码的18个字符显示(数据对象编号(6)+文件编号(3)+块编号(6)+行编号(3)=18位),其中
A-Z <==> 0 - 25 (26)
a-z <==> 26 - 51 (26)
0-9 <==> 52 - 61 (10)
+/ <==> 62 - 63 (2)
共64位,明白这个后,就可以计算出10进制的编码值,计算公式如下:
d * (b ^ p)
其中:b就是基数,这里就是64,p就是从右到左,已0开始的位置数
比如:上面的例子文件号AAF,具体的计算应该是:
5*(64^0)=5;
0*(64^1)=0;
0*(64^2)=0;
文件号就是0+0+5=5
刚才提到的是rowid的显示方式:基于64位编码的18个字符显示,
其实rowid的存储方式是:10 个字节即80位存储,其中数据对象编号需要32 位,相关文件编号需要10 位,块编号需要22,位行编号需要16 位,
由此,我们可以得出显示方式与存储方式较小的一种决定类别总量的最大值,
64=2^6,即6位64进制等价于36位2进制,3位64进制等价于18位2进制,可以看出存储方式较小:
32bit的object number,每个数据库最多有4G个对象
10bit的file number,每个对象最多有1022个文件(2个文件预留)
22bit的block number,每个文件最多有4M个BLOCK,已知dbblock为8k,即每个文件最大32G
16bit的row number,每个BLOCK最多有64K个ROWS,已知dbblock为8k,即每个ROWS最小为1bit(目前不存在如此小的类型,也就存在如此小的行,估计oracle是随后为扩展8k页预留)。
dbblock与每行的字节数没有明确的数据关系,因为varchar2等类型是变长的。

2.rowid相关的有用的sql
最简单的基于rowid的显示方式得到的响应的64位编码对应值的sql:
select rowid ,
substr(rowid,1,6) "OBJECT",
substr(rowid,7,3) "FILE",
substr(rowid,10,6) "BLOCK",
substr(rowid,16,3) "ROW"
from TableName;
ROWID              OBJECT       FILE   BLOCK        ROW
------------------ ------------ ------ ------------ ------
AAABc4AADAAAGLUAAA AAABc4       AAD    AAAGLU       AAA
AAABc4AADAAAGLUAAB AAABc4       AAD    AAAGLU       AAB
AAABc4AADAAAGLUAAC AAABc4       AAD    AAAGLU       AAC
AAABc4AADAAAGLUAAD AAABc4       AAD    AAAGLU       AAD
AAABc4AADAAAGLUAAE AAABc4       AAD    AAAGLU       AAE
通过dbms_rowid这个包,可以直接的得到具体的rowid包含的信息(十进制):
select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id ,dbms_rowid.rowid_row_number(rowid) num from bruce_t where rownum<5;
OBJECT_ID    FILE_ID   BLOCK_ID        NUM
---------- ---------- ---------- ----------
      5944          3      25300          0
      5944          3      25300          1
      5944          3      25300          2
      5944          3      25300          3
一些使用ROWID的函数
ROWIDTOCHAR(rowid) :将ROWID转换成STRING
CHARTOROWID('rowid_string') :将STRING转换成ROWID
另外,就是自己写的一些函数:(下面的函数是网友eygle提供)
create or replace function get_rowid (l_rowid in varchar2) return varchar2
is
 ls_my_rowid     varchar2(200);        
 rowid_type     number;        
 object_number     number;        
 relative_fno     number;        
 block_number     number;        
 row_number     number;
begin
    dbms_rowid.rowid_info(l_rowid,rowid_type,object_number,relative_fno, block_number, row_number);        
    ls_my_rowid := 'Object# is      :'||to_char(object_number)||chr(10)||
        'Relative_fno is :'||to_char(relative_fno)||chr(10)||
        'Block number is :'||to_char(block_number)||chr(10)||
        'Row number is   :'||to_char(row_number);
    return ls_my_rowid ;
end;       
/
show err;
应用上面的函数如下:
SQL> select get_rowid(rowid), name from bruce_t;
GET_ROWID(ROWID)                                                                 NAME
-------------------------------------------------------------------------------- --------------------------------
Object# is      :5944                                                      BruceLau
Relative_fno is :3                                                             
Block number is :25300                                                         
Row number is   :0                                                             
Object# is      :5944                                                     MabelTang
Relative_fno is :3                                                             
Block number is :25300                                                         
Row number is   :1

ROWID:ROWID为该表行的唯一标识,是一个伪列,可以用在SELECT中,但不可以用INSERT, UPDATE来修改该值。
注意:ROWID的表指:table,cluster table, partition table, subpartition table, index, index partitions and subpartitions(注意:不包含index-organized tables).
每个表Oracle都存在一个伪列ROWID,这个伪列可以用SELECT查看,但是不可以用INSERT, UPDATE来修改。
你也不可以用DELETE来删除ROWID列,Oracle使用ROWID列来建立内部索引。
你可以引用ROWID的值,但ROWID并不存放在数据库中,你可以创建一个表包含ROWID数据类型,但Oracle不保证该值是合法的rowids。用户必须确保该rowid值是真实合法的。
UROWID:
    UROWID(通用ROWID,逻辑ROWID): 表的行地址,表指的是index-organized tables。
IOT中物理rowid是可能变化的,另外Oracle要依靠rowid来建立表的索引,所以对IOT表来物理rowid就不行了。
Oracle以表的主键为基础引入UROWID,在物理rowid基础上建立了第二个索引。每一个逻辑rowid使用一个第二索引和一个物理推测(IOT中标识块的行)。
    UROWID支持逻辑和物理的rowids,列UROWID类型可以存储各种rowids, 从8.1以后的Oracle才有UROWID类型,它也可以用来保存以前的ROWID类型数据信息。
    更新IOT的主键可能导致ROWID改变,该行的UROWID也会改变。
Oracle使用rowid数据类型存储行地址,rowid可以分成两种,分别适于不同的对像
Physical rowids:存储ordinary table,clustered table,table partition and subpartition,indexe,index partition and subpartition
Logical rowids :存储IOT的行地址
另一种rowid类型叫universal rowed(UROWID),支持上述physical rowid和logical rowed,并且支持非oracle table,即支持所有类型的rowid,但COMPATIBLE必须在8.1或以上.

1.1 ROWID伪列
    每个表在oracle内部都有一个ROWID伪列,它在所有sql中无法显示,不占存储空间;它用于从表中查询行的地址或者在where中进行参照,一个例子如下:
    SELECT ROWID, last_name FROM employees;
    Oracle内部使用保留在ROWID伪列中的值构建索引结构
    再次强调一次,rowid伪列不存储在数据库中,它不是数据库数据,这是从database及table的逻辑结构来说的,事实上,在物理结构上,每行由一个或多个row pieces组成,每个row piece的头部包含了这个piece的address,即rowid.从这个意义上来说,rowid还是占了磁盘空间的.
   我们在创建表时,可以为列指定为rowid数据类型,但oracle并不保证列中的数据是合法的rowid值,必须由应用程序来保证,另外,类型为rowid的列需要6 bytes存储数据
1.2, physical rowids
只在行存在,它的物理地址rowid就不会变化,除非export/import,根据rowid可以直接定位到block去fetch数据,所以physical兼具有高稳定(stability)和高性能(performance)的特点.
这里要注意一点,对于clustered table来说,根据它的存储特点,在同一个block中的不同table的行可能具有同一个rowid;而nonclustered table,每一行或初始行片(initial row piece)都有唯一的rowid
要注意rowid的地址固定的特点,在一个block的某一行被delete并commit后,它占据的address可以被其它事务新insert的行重用.
Physical rowid可以是下面任一一种格式:
1) Extended rowid
  使用表空间相关的数据块地址,8i及以上使用这种格式
2) Restricted rowid
   使用数据库范围的数据址地址,oracle 7或更早前的版本使用
1.2.1 extened rowid
      扩展行地址是64编码的物理地址,编码字符是A-Z, a-z, 0-9, +,and/.
      由4部分组成OOOOOOFFFBBBBBBRRR (obj#file#block#row#)
    
      OOOOOO -–data object number
       FFF –-表空间相对的数据文件号
       BBBBBB –-块号
       RRR ---行号
       注意不是16进制表示
      SQL> select rowid,name from obj$ where rownum<=10;
ROWID             NAME
------------------ ------------------------------
AAAAASAABAAAAB6ABc ACCESS$
AAAAASAABAAAC1QAAK AGGXMLIMP
AAAAASAABAAAC1QAAL AGGXQIMP
AAAAASAABAAAGiRAAI ALERT_QT
AAAAASAABAAAGiRAAh ALERT_QUE
AAAAASAABAAAGujAAo ALERT_QUE$1
AAAAASAABAAAGujAAp ALERT_QUE$1
AAAAASAABAAAGiRAAf ALERT_QUE_N
AAAAASAABAAAGiRAAe ALERT_QUE_R
AAAAASAABAAAGiRAAG ALERT_TYPE
我们可以使用dbms_rowid从extened rowid中抽取各部分信息,或者将extened rowid转换成restricted rowed,详细的信息参见sys.dbms_rowid的规范
#根据rowid抽块对像编号
SQL> select dbms_rowid.rowid_object('AAAAASAABAAAGiRAAG') obj# from dual;
     OBJ#
----------
       18
#根据rowid抽取表空间相对文件号
SQL> select dbms_rowid.rowid_relative_fno('AAAAASAABAAAGiRAAG') rfile# from dual;
    RFILE#
----------
        1
#根据rowid抽取块号
SQL> select dbms_rowid.ROWID_BLOCK_NUMBER('AAAAASAABAAAGiRAAG') block# from dual;
   BLOCK#
----------
    26769
#根据rowid抽取行号
SQL> select dbms_rowid.rowid_row_number('AAAAASAABAAAGiRAAG') row# from dual;
     ROW#
----------
        6
#将extended rowid转换成为restricted rowid
SQL> select dbms_rowid.rowid_to_restricted('AAAAASAABAAAGiRAAG',0) restricted_rowid from dual;
RESTRICTED_ROWID
------------------
00006891.0006.0001
1.2.2restricted rowid
限制地址行号与扩展地址行号编码方式不一样,它在内部使用二进制方式表示,当用select查询时,会转换成varchar2/16进制的混合形式,它的组织方式如下:
BBBBBBBB.RRRR.FFFF (block#.row#.file#)
注意,这里的文件号是绝对文件号,而extended rowid中是相对文件号(相对表空间)
Restricted rowid中不再有object number,因为从绝对文件号可以唯一确定数据块
样例可以参考前面的00006891.0006.0001
    另外请注意,块中的行号是从0开始
除了用dbms_rowid来抽取rowid的不同部分外,也可以用substr
#extended rowid
SQL> SELECT ROWID,
2007-02-01 15:19:28
2         SUBSTR(ROWID,1,6) "OBJECT",
3         SUBSTR(ROWID,7,3) "FIL",
4         SUBSTR(ROWID,10,6) "BLOCK",
5         SUBSTR(ROWID,16,3) "ROW"
6   from obj$ where rownum<=5;
ROWID              OBJECT       FIL    BLOCK        ROW
------------------ ------------ ------ ------------ ------
AAAAASAABAAAAB6AAa AAAAAS       AAB    AAAAB6       AAa
AAAAASAABAAAAB6AAu AAAAAS       AAB    AAAAB6       AAu
AAAAASAABAAAAB6AAF AAAAAS       AAB    AAAAB6       AAF
AAAAASAABAAAAB6AAv AAAAAS       AAB    AAAAB6       AAv
AAAAASAABAAAAB6AAZ AAAAAS       AAB    AAAAB6       AAZ
#restricted rowid
SQL> SELECT ROWID,
2         SUBSTR(ROWID,15,4) "FILE",
3         SUBSTR(ROWID,1,8) "BLOCK",
4         SUBSTR(ROWID,10,4) "ROW"
5   from obj$ where rownum<=5;
ROWID              FILE     BLOCK            ROW
------------------ -------- ---------------- --------
AAAAASAABAAAAB6AAa 6AAa     AAAAASAA         AAAA
AAAAASAABAAAAB6AAu 6AAu     AAAAASAA         AAAA
AAAAASAABAAAAB6AAF 6AAF     AAAAASAA         AAAA
AAAAASAABAAAAB6AAv 6AAv     AAAAASAA         AAAA
AAAAASAABAAAAB6AAZ 6AAZ     AAAAASAA         AAAA
请注意extented rowid与restricted rowid的编码方式不一样,大家不能拿两种不同编码方式的组件作比较,比如AAAAASAABAAAAB6AAa 这行的File#在两种方式下是有不同的值,表示不同的意义,没有可比性.
下面的语句可以查看表的数据分布在几个文件中
SQL> SELECT COUNT(DISTINCT(SUBSTR(ROWID,7,3))) "FILES" FROM BOSSSTATSDATA;
     FILES
----------
        17
#下面验证bossstatsdata的数据确实分布在17个文件中
SQL> select count(file_name) from dba_data_files where TABLESPACE_NAME= (select TABLESPACE_NAME from user_tables where table_name='BOSSSTATSDATA');
COUNT(FILE_NAME)
----------------
              17
总结Rowid的使用场景
1) 构建索引结构, 每个key都有一个rowid指向相应的表行
2) rowid是访问表行的最快的方法
3) rowid可用于观察表数据是怎样组织的
4) rowid是表行的唯一标识符
在任何DML中使用rowid时,应该注意确保相关的行不会改变物理地址(不会被export/import,delete)
1.3 logical rowids
    用于表达IOT行地址的Logical rowid存储在索引的叶子节点中,会随着索引entry的insert在块内或块间移动,所以,它不是基于物理地址而是基于primary key的标识符,所以取名叫logcial rowid
Oracle使用logical rowids来构建IOT的secondary indexes
由于在实际的应用中很少会使用到IOT这种对像,关于logical rowid更详细的描述可以参见<<concepts>>中相关章节
Part IV Oracle Database Application Development
26 Native Datatypes
Overview of ROWID and UROWID Datatypes
1.4 非oracle table中的rowid
在非oracle系统中,不同的系统有不同的rowid格式,并且,不能使用前述标准的rowid到varchar2/16进制的转换方法,
所以,在这种情况下,应用程序可以使用rowid数据类型,不过要使用非标准的转换方法 (最长256bytes的16进制)
非oracle 系统中的rowid也能存储在UROWID数据类型中

Oracle rowid的更多相关文章

  1. oracle rowid 详解

    oracle rowid详解 今天是2013-09-15,存储在数据库中的每一行数据都有一个地址,oracle使用rowid数据类型在存储地址.rowid有如下类别: 1)physical rowid ...

  2. KingbaseES CTID 与 Oracle ROWID

    熟悉oracle的人都知道ROWID可用于快速的数据访问,KingbaseES 由于自身MVCC机制的原因,ctid 作为 oracle rowid 的替代方案不合适,但currtid 还是基本可以满 ...

  3. ORACLE rowid,file# 和 rfile#

    rowid简介 rowid就是唯一标志记录物理位置的一个id,在oracle 8版本以前,rowid由file#+block#+row#组成,占用6个bytes的空间,10 bit 的 file# , ...

  4. oracle rowid 使用

    ROWID是数据的详细地址,通过rowid,oracle可以快速的定位某行具体的数据的位置. ROWID可以分为物理rowid和逻辑rowid两种.普通的堆表中的rowid是物理rowid,索引组织表 ...

  5. Oracle ROWID具体解释

    1.ROWID定义 ROWID:数据库中行的全局唯一地址 对于数据中的每一行,rowid伪列返回行的地址.rowid值主要包括下面信息: 对象的数据对象编号 该行所在的数据文件里的数据块 该行中数据块 ...

  6. oracle rowid 研究

    SQL> create table tab01(id integer,val varchar(4)); Table created. SQL> insert into tab01 valu ...

  7. ORACLE rowid切分大表

    通过如下sql获取rowid切分范围 ) || dbms_rowid.rowid_create(, DOI, lo_fno, lo_block, ) ) || ) || dbms_rowid.rowi ...

  8. Oracle 11g 编译使用BBED

    环境:RHEL 6.4 + Oracle 11.2.0.4 1. 拷贝缺失文件 2. 编译BBED 3. BBED使用测试 Reference 1. 拷贝缺失文件 11g中缺失几个相关文件,但我们实际 ...

  9. Oracle corrupt block(坏块) 详解

    转自:http://blog.csdn.net/tianlesoftware/article/details/5024966 一. 坏块说明 1.1 相关链接 在看坏块之前,先看几个相关的链接,在后面 ...

随机推荐

  1. nginx相关配置说明

    基础: nginx配置文件主要分为六个区域:main section.events section.http section.sever section. location section.upstr ...

  2. Centos 7 通过挂载系统光盘搭建本地yum仓库的方法

    实验环境:CentOS 7 1:在media文件下创建一个目录  #创建一个www文件 cd /media/www 2: 挂载光盘,将光盘挂载在刚才创建的www文件下 mount /dev/cdrom ...

  3. JTAG和SWD连接关系图

    经实际测试 SWD最少接线方法: 1.VTref与Vsupply短接 2.JLINK的SWDIO与目标板SWDIO相连 3.JLINK的SWCLK与目标板SWCLK相连 4.JLINK任意一个GND与 ...

  4. 【MySQL】探究之常用SQL

    一些SQL命令(不断更新,我总记不住,哭) List 建库建表 表的重命名(不区分大小写) 列的重命名 编码 修改结构 添加删除索引 大批量删除 binlog相关 select相关 数据库备份和恢复 ...

  5. cg tut

    Gesture Drawing with Alex Woo Gesture Drawing with Alex Woo and Louis Gonzales http://eisneim.com/?p ...

  6. vim全选,全部复制,全部删除

    全选(高亮显示):按esc后,然后ggvG或者ggVG 全部复制:按esc后,然后ggyG 全部删除:按esc后,然后dG 解析: gg:是让光标移到首行,在vim才有效,vi中无效 v : 是进入V ...

  7. 关于block的一些理解

    之前一直都是用这别人或者是系统系统封装好的block,用这都挺好,可以访问那些定义了block变量的函数变量在block中使用. 首先总结一个block的用法:1.block有些类似于函数的指针 拥有 ...

  8. ios中strong和weak的解释理解

    来自stackoverflow解释的挺有意思的 Imagine our object is a dog, and that the dog wants to run away (be dealloca ...

  9. eclipse几个注意的地方

    1.eclipse+tomcat调试java web,eclipse中更新了代码,而tomcat中代码不同步更新 1)双击eclipse tomcat server,勾选"Modules a ...

  10. 分析Tornado的协程实现

    转自:http://www.binss.me/blog/analyse-the-implement-of-coroutine-in-tornado/ 什么是协程 以下是Wiki的定义: Corouti ...