Oracle ROWID与RDBA

1.1     Rowid的意义

1.      Rowid就是用来标记表中每一行的行地址的,分为逻辑rowid,物理rowid和外部rowid,一般索引组织表的行地址使用逻辑rowid,堆组织表、 表簇、表分区、和索引分区的行地址使用物理rowid。外部rowid则是用来标识外来表(非oracle数据库的表)的行。

3.      Oracle 数据库在内部使用 rowids用于构造索引,最常见的 B 树索引,包含一个被划分成多个键范围的排序列表。索引键值(就是叶子节点)中存储了表每条记录的rowid,通过索引查找实际就是通过索引,找到记录的rowid,从而定位到表中的rowid代表的行。

所以,Rowid存在的意义:

Rowidsare the fastest means of accessing particular rows. –加快访问

Rowidsprovide the ability to see how a table is organized. –提供研究表组织方式的途径

Rowidsare unique identifiers for rows in a given table. –rowid是表中每一行的唯一标识符

1.2     Rowid也是一种数据类型

HR >alter table test addrowid_1 rowid;      ---增加一列可rowid的行

Table altered.

HR >insert into testvalues(sysdate-2,'AAAXR0AAdAAAAHdAAA');---插入要按照rowid规则,否则无效

1 row created.

HR >select t.*,t.rowidfrom test t;

ID                 |ROWID_1           |ROWID

-------------------|------------------|------------------.

2013-06-14 18:42:42|                  |AAAXR0AAdAAAAHdAAA

2013-06-1318:44:01|AAAXR0AAdAAAAHdAAA|AAAXR0AAdAAAAHdAAB

Rowid伪列(pseudo):

每个表都有以个伪列,类型就是rowid,用于标识每行的rowid。它不占用存储空间,也没法用describe查看。可以把它看成一个行数,不过每一行返回的值不一样。可以使用rowid列名来查看每一行的rowid,上面已经用到伪列了。

1.3     Rowid是怎么表示的?

以oracle8i为例(8i以来就没有改变,但是大文件表空间有点不一样!)

Rowid一共10字节,80bits,由四部分组成:分别是oooooooo.fff.bbbbb.rrrr,其中包括32bit的对象号。10bits的文件号,22bits的块号,16bits的行号(在一个块中)。从rowid的表示方法就知道:

一个表空间最多有1024个数据文件,除去全0和全1,是1022

一个数据文件最多有4m(2^22)个块,这就解释了为什么SMF数据文件最大是128G(块按照最大的32k计)。

一个块最多是65535(2^16)行。那么一个数据文件最大的行数就是2^38行,2千多亿行。

但是,rowid实际的表示方法为64base编码,可以去看看base64编码与数字,字母以及字符的对应表:

0818b9ca8b590ca3270a3433284dd417.png

例如:AAANO8AAKAAAAF5AAA,

把这个rowid划分为4部分:按照6,3,6,3的划分规则

就是:AAANO8   AAK   AAAAF5   AAA

转换为十进制数:

对象编号:

60*(64^0)=60

14*(64^1)=896

13*(64^2)=53248

所以对象编号就是十进制的:53248+896+60=54204

转换为二进制数: 1101001110111100

同理,文件编号:K=10

块号:57+5*64=325

行号:0

1.4     RowID与rdba转换:

1.      使用字符串提取函数提取各部分(共四部分):

select rowid ,

substr(rowid,1,6) "OBJECT",

substr(rowid,7,3) "FILE",

substr(rowid,10,6) "BLOCK",

substr(rowid,16,3) "ROW"

from&TableName whererownum<=5;

HR >select rowid,

2 substr(rowid,1,6) "OBJECT",

3 substr(rowid,7,3) "FILE",

4 substr(rowid,10,6) "BLOCK",

5 substr(rowid,16,3) "ROW"

6  from&TableName where rownum<=5;

Enter value fortablename: test

old   6: from &TableName where rownum<=5

new   6: from test where rownum<=5

ROWID             |OBJECT      |FILE |BLOCK       |ROW

------------------|------------|------|------------|------

AAAXR0AAdAAAAHdAAA|AAAXR0      |AAd  |AAAAHd      |AAA

AAAXR0AAdAAAAHdAAB|AAAXR0      |AAd  |AAAAHd      |AAB

2.      使用包DBMS_GETROW实现到rdba的转换

selectrowid,

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 &table_name whererownum<5;

HR >selectrowid,

2 dbms_rowid.rowid_object(rowid) object_id,

3 dbms_rowid.rowid_relative_fno(rowid) file_id,

4 dbms_rowid.rowid_block_number(rowid) block_id,

5 dbms_rowid.rowid_row_number(rowid) num

6  from&table_name where rownum<5;

Enter value fortable_name: test

old   6: from &table_name where rownum<5

new   6: from test where rownum<5

ROWID             | OBJECT_ID|   FILE_ID| BLOCK_ID|       NUM

------------------|----------|----------|----------|----------

AAAXR0AAdAAAAHdAAA|     95348|       29|       477|         0

AAAXR0AAdAAAAHdAAB|     95348|        29|       477|         1

3.      使用函数获取:

create or replace function get_rowid    --建立函数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

object_number,relative_fno, block_number, row_number);

ls_my_rowid := 'Object#is      :'||to_char(object_number)||chr(10)||

'Relative_fnois :'||to_char(relative_fno)||chr(10)||

'Blocknumber is :'||to_char(block_number)||chr(10)||

'Rownumber is   :'||to_char(row_number);

return ls_my_rowid ;

end;

/

HR >selectget_rowid(rowid) from test;

GET_ROWID(ROWID)

Object#is      :95348

Relative_fnois :29

Block numberis :477

Row numberis   :0

Object#is      :95348

Relative_fnois :29

Block numberis :477

Row numberis   :1

1.5     特殊情况----大文件表空间

由于大文件表空间只有一个文件,那么它就没有必要拥有相对文件号了,他把原来的10位的文件号给了块号,这样块号有32位,就是4个g大小,这就证实了:当块大小为32k时候,大文件最大可以达到128t。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐