rowid 说明
rowid是伪列(pseudocolumn),伪列的意思是实际上这一列本身在数据字典中并不存在,在查询结果输出时它被构造出来的。
rowid并不会真正存在于表的data block中,但是他会存在于index当中,用来通过rowid来寻找表中的行数据。
Rowid的结构
现在通用的9i,10g,11g用的都是扩展的rowid了。
ROWID 格式:
扩展的ROWID 在磁盘上需要10 个字节的存储空间,并使用18 个字符来显示。
它包含下列组成元素:
1. 数据对象编号:每个数据对象(如表或索引)在创建时都分配有此编号,并且此编号在数据库中是唯一的(dba_objects中的data_object_id,不是object_id)
2. 相关文件编号:此编号对于表空间中的每个数据文件是唯一的
3. 块编号:表示包含此行的块在数据文件中的位置
4. 行编号:标识块头中行目录位置的位置
在内部,存储的10个字节(bytes),即80位(bit)又按如下规则进行划分:
(1)数据对象编号需要32 bit
(2)相关文件编号需要10 bit
(3)块编号需要22 bit
(4)行编号需要16 bit
在oracle 8以前,一个rowid占用6个字节大小的存储空间(10bit file#+22bit block#+16bit row#), rowid格式为:BBBBBBBB.RRRR.FFFF。
在oracle 8以后, rowid的存储空间扩大到了10个字节(32bit object#+10bit rfile#+22bit block#+16bit row#),文件号仍然用10位表示,只是不再需要置换,为了向后兼容,同时引入了相对文件号(rfile#),所以从Oracle7到Oracle8,Rowid仍然无需发生变化.
Rdba(Tablespace relative database block address)就是rowid中的rfile#+block#.
rowid这样改变之后,数据库中数据库文件个数的限制从整个数据库最多只能有的2^10-2=1022个数据文件(去掉全0和全1), 变为了每个表空间中可以最多有2^10-2个数据文件。
所以说,数据库能支持的数据文件最大数是受rowid的长度限制的。
需要注意的是: local index中存储的rowid是6个字节,而global index中存储的rowid是10个字节。
那么增加的32bit object# 这个前缀主要就是用来定位表空间的,同时这个object#其实对应的就是data_object_id,由于一个段对象只能属于一个表空间,同时data_object_id就是标识了一个段的物理存储id.因此object#+rfile#就可以唯一定位当前的rowid是在那个数据文件上了。
可以通过dbms_rowid这个包来转换我们的rowid成不同组成部分:
dbms_rowid.rowid_object(rowid)---> 32bit object#
dbms_rowid.rowid_relative_fno(rowid)---> 10bit rfile#
dbms_rowid.rowid_block_number(rowid)---> 22bit block#
dbms_rowid.rowid_row_number(rowid)---> 16bit row#
扩展的ROWID 使用以64 为基数的编码方案来显示,该方案将六个位置用于数据对象编号、三个位置用于相关文件编号、六个位置用于块编号、三个位置用于行编号。
以64 为基数的编码方案使用字符“A-Z”、“a-z”、“0-9” 和“/”。共有64 个字符,如下例所示:
SQL> SELECT department_id, rowid FROM hr.departments;
EMPNO ROWID
---------- ------------------
7488 AAAMfPAAEAAAAAgAAA
7499 AAAMfPAAEAAAAAgAAB
7521 AAAMfPAAEAAAAAgAAC
7566 AAAMfPAAEAAAAAgAAD
7654 AAAMfPAAEAAAAAgAAE
7698 AAAMfPAAEAAAAAgAAF
7782 AAAMfPAAEAAAAAgAAG
7788 AAAMfPAAEAAAAAgAAH
7839 AAAMfPAAEAAAAAgAAI
7844 AAAMfPAAEAAAAAgAAJ
7876 AAAMfPAAEAAAAAgAAK
7900 AAAMfPAAEAAAAAgAAL
在本例中:
AAAMfP 是数据对象编号
AAE 是相关文件编号
AAAAAg是块编号
AAA是EMPNO=7488 的部分的行编号