暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ROWID与RDBA的转换

原创 eygle 2019-10-15
1579

在上一节提到,对于大文件表空间其相对文件号(RELATIVE_FNO)为1024:

SQL> select file_name,file_id,relative_fno from dba_data_files
  2  where relative_fno=1024;
FILE_NAME                                             FILE_ID RELATIVE_FNO
-------------------------------------------------- ---------- ------------
+DATADG/smsboss/datafile/bossmgr.271.577809233              5         1024


那么文件号和相对文件号有什么区别呢?又为什么会有这两个东西呢?


Oracle的ROWID及数据库限制


众所周知,数据存放在数据文件中,因为其存储,数据的一系列属性就随之确定,这些属性包括记录存储所在的数据文件(file#)、所属的数据库对象(obj#)、所在的数据块号(block_no#)以及在表中的行号等,将这些属性合并起来就构成了Oracle的ROWID。


Oracle的ROWID又可以分为两种:物理ROWID和逻辑ROWID。索引组织表使用逻辑ROWID,其他类型的表使用物理ROWID。这里主要介绍物理ROWID。


ROWID在表中并不存在,但是查询表时可以使用这一伪列:

SQL> select rowid,t.* from scott.dept t;
ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAACXuAABAAAGDyAAA         10 ACCOUNTING     BEIJING
AAACXuAABAAAGDyAAB         20 RESEARCH       BEIJING
AAACXuAABAAAGDyAAC         30 SALES          BEIJING
AAACXuAABAAAGDyAAD         40 OPERATIONS     BEIJING


因为ROWID可以唯一地标识一条记录,所以索引(Index)中存储了ROWID值,通过索引访问记录实际上也就是通过从索引中获得ROWID,再根据ROWID到数据表中定位记录的过程。

前面提到,MOVE表之后索引需要重建就是因为存储位置发生了改变,索引中的ROWID无法定位到新的数据存储,所以需要重建。而Shrink过程因为使用的是DML操作,所以索引可以同时被维护,完成操作之后不再需要重建索引。


Oracle的ROWID在不同的版本中一直在不断变化:


 · 在Oracle 6中,ROWID中仅用6 bit代表文件号,所以数据库最多只能有26=64个数据文件(去掉全0和全1,实际上最多只能代表62个文件);

 · 到Oracle 8,ROWID组成扩展为FFFF.BBBBBBBB.RRRR,占用6个字节(其中10 bit file# + 22bit block# + 16bit row#);

 · 在Oracle 8i中,Oracle更是在ROWID中引入了dataobj#,现在的ROWID格式变更为OOOOOO.FFF.BBBBBB.RRR,占用10个字节。新的ROWID采用Base64编码,一共有18位,代表80位二进制数,其中O是对象号,F是文件号,B是块号,R是行号,这80位的方式为32bit obj# +10bit rfile#+22bit block# +16bit row#。


ROWID的64个编码及代表的数字顺序如表5-3所示。

表5-3    ROWID的64个编码及其代表的顺序

image.png


通过上文可以知道,在Oracle 8i之前,ROWID中存放的是文件号,为了扩展数据库的存储能力,从Oracle 8i开始ROWID的组成中增加了对象号,而file#变成了rfile#。文件号到相对文件号的改变,使得数据库的数据文件数限制从全库不能超过1023个变成了每个表空间不能超过1023个数据文件。这就极大地扩展了Oracle数据库的存储能力。


了解了ROWID的构成之后,就可以很清楚地理解Oracle数据库的一些内部限制,例如:


 · 每表空间最大文件数量=210=1024,去掉全0和全1,通常为1022个;

 · 每数据文件最大数据块数量=222=4M Block,通常每个文件最大Block数量为4M个Oracle块;

 · 每个Block中的行数=216=65536,通常每个Block最多只能容纳65536条记录。


BigFile表空间的ROWID


上一节介绍的是Oracle 10g之前的ROWID格式,Oracle 8i以来的ROWID格式为:

OOOOOO.FFF.BBBBBB.RRR


Oracle 10g引入了BigFile表空间,大文件表空间可以容纳更多的数据块,这是因为ROWID算法发生了改变,由于大文件表空间只能包含一个文件,所以ROWID中不再需要rfile#,大文件表空间的ROWID格式现在为:

OOOOOO.LLLLLLLLL.RRR


其中L代表新的Block号,现在有32位用于代表Block号,所以对于大文件表空间,现在最大能够容纳4G个Block。如果block_size为32kB,大文件表空间最大容量可以达到4G×32kB =128TB。


使用dbms_rowid包获得ROWID的详细信息


ROWID中包含了记录的详细信息,通过Oracle提供的系统包dbms_rowid可以获得这些信息,我们可以通过一个自定义函数来简化该系统包的使用:

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;         
/


来看一下其用法:

SQL> select rowid,a.* from dept a;
ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAABiPAABAAAFRSAAA         10 ACCOUNTING     NEW   YORK
AAABiPAABAAAFRSAAB         20 RESEARCH       DALLAS
AAABiPAABAAAFRSAAC         30 SALES          CHICAGO
AAABiPAABAAAFRSAAD         40 OPERATIONS     BOSTON
通过get_rowid函数可以转换出ROWID中的信息:
SQL> select get_rowid('AAABiPAABAAAFRSAAA') row_id from dual;
ROW_ID
------------------------------------------------------------
Object# is      :6287
Relative_fno is :1
Block number is :21586
Row number is   :0


在Oracle 10g中,针对大文件表空间,DBMS_ROWID包中增加TS_TYPE_IN参数用于区分SMALLFILE或BIGFILE表空间。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论