Oracle ROWID与RDBA

来源:互联网 发布:win7禁止程序访问网络 编辑:程序博客网 时间:2024/05/21 18:32


Oracle ROWIDRDBA


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编码与数字,字母以及字符的对应表:


例如:AAANO8AAKAAAAF5AAA,

把这个rowid划分为4部分:按照6363的划分规则

就是: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

 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_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。

 

原创粉丝点击