Oracle rowid

一.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包含下列组成元素:

  1. 数据对象编号(32 bit):对应dba_objects.data_object_id.此编号确定所属表空间,因为一个段对象只属于一个表空间                           
  2. 相对文件编号(10 bit):对应dba_extents.relative_fno.此编号对于表空间中的每个数据文件是唯一的,故每个表空间中可以最多有2^10-2个数据文件
  3. 块编号(22 bit):表示包含此行的块在数据文件中的位置
  4. 行编号(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查询出的值)

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。