一.Rowid
rowid是伪列(pseudocolumn),伪劣的意思是实际上这一列本身在数据字典中并不存在,在查询结果输出时它被构造出来的。
rowid并不会真正存在于表的data block中,但是他会存在于index当中,用来通过rowid来寻找表中的行数据
二.Rowid的结构
限制rowid:用于早期Oracle版本(Oracle 8 以前),rowid由(10 bit)file#+(22 bit)block#+(16 bit)row#组成,占用6个bytes的空间
注:file#为10位,故整个数据库最多只能有的2^10-2=1022个数据文件(去掉全0和全1)
扩展rowid:由data_object#+rfile#+block#+row#组成,占用10个bytes的空间,显示为18位的字符串
扩展rowid包含下列组成元素:
- 数据对象编号(32 bit):对应dba_objects.data_object_id.此编号确定所属表空间,因为一个段对象只属于一个表空间
- 相对文件编号(10 bit):对应dba_extents.relative_fno.此编号对于表空间中的每个数据文件是唯一的,故每个表空间中可以最多有2^10-2个数据文件
- 块编号(22 bit):表示包含此行的块在数据文件中的位置
- 行编号(16 bit):标识块头中行目录位置的位置
定位一行记录的顺序是:数据对象(表空间)-->数据文件(此表空间中的)-->块编号(此数据文件中的)-->定位行(此块中的)
可以通过dbms_rowid这个包来转换我们的rowid成不同组成部分:
dbms_rowid.rowid_object(rowid)---> 32bit data_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相关知识点
rdba(Tablespace relative database block address)就是rowid中的rfile#+block#.
dba一般指绝对数据块地址。如果数据文件超过>=1024即2的10次方的话,仅用绝对dba在内部没办法表示的,内部一般是用rdba来表示,它限定了某个表空间
四.测试
dba_objects.object_id 和 dba_objects.data_object_id :在对象建立当初,这两个id是一样的,前者代表的是这个对象的名字的id,是不会有变化的。即使你给这个表改一下名字,也不会有变化;后者,(也就是ROWID中的前六位代表的位置)是数据对象的位置(数据段)一个编号。如果把这个表换一个表空间,这个编号就会变化,同时rowid也会变化。
1 SQL> create table t(id number,name varchar2(32)); 2 SQL> insert into t(id,name) values(0,'yy'); 3 SQL> commit; 4 SQL> select rowid,t.* from t; 5 6 ROWID ID NAME 7 ------------------ ---------- -------------------------------- 8 AAAWSPAABAAAYaxAAA 0 yy 9 10 SQL> select dbms_rowid.rowid_object(rowid) object_id from t; 11 12 OBJECT_ID 13 ---------- 14 91279 15 16 SQL> 17 18 19 SQL> Select OWNER,OBJECT_NAME,OBJECT_ID,DATA_OBJECT_ID,OBJECT_TYPE 20 2 From dba_objects 21 3 Where object_name='T'; 22 23 OWNER OBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE 24 ------------ ---------- --------- -------------- ---------- 25 SYS T 91279 91279 TABLE 26 27 28 SQL> 29 30 --改变表空间,即改变DATA_OBJECT_ID 31 SQL> alter table t move tablespace TABROWID; 32 33 SQL> Select OWNER,OBJECT_NAME,OBJECT_ID,DATA_OBJECT_ID,OBJECT_TYPE 34 2 From dba_objects 35 3 Where object_name='T'; 36 37 OWNER OBJECT_NAM OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE 38 ---------- ---------- ---------- -------------- ------------------- 39 SYS T 91279 91280 TABLE 40 41 SQL> 42 43 ----查看rowid是否变化:变化 44 SQL> select dbms_rowid.rowid_object(rowid) DATA_OBJECT_ID object_id from t; 45 46 DATA_OBJECT_ID 47 ---------- 48 91280 49 SQL>
结论:rowid中的数据对象编号对应dba_objects.DATA_OBJECT_ID
需要注意的是:当数据库文件超过1024个文件数,如何查找数据块所在文件号
1 --根据表空间名、REL_FNO确定数据块所在文件file_id 2 1.查看数据块的REL_FNO,BLOCKNO 3 SELECT 4 dbms_rowid.rowid_relative_fno(rowid) REL_FNO, 5 dbms_rowid.rowid_block_number(rowid) BLOCKNO 6 FROM TEST_OBJECTS1 7 WHERE ROWNUM < 10; 8 9 2.确定文件编号file_id 10 select segment_name,relative_fno,file_id 11 from dba_extents 12 where segment_name='TEST_OBJECTS1' and relative_fno=&REL_FNO(第一个sql查询出的值)