Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1780850
  • 博文数量: 413
  • 博客积分: 8399
  • 博客等级: 中将
  • 技术积分: 4325
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 10:44
文章分类

全部博文(413)

文章存档

2015年(1)

2014年(18)

2013年(39)

2012年(163)

2011年(192)

分类: Oracle

2012-09-09 23:27:58

rowid是oracle中的一个重要的概念。要理解索引,必须先搞清楚rowid。rowid它是一个伪列,它并不实际存在于表中。它是oracle在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列。所以rowid表示了一行数据的物理地址信息。
 
1. rowid的格式:

1)rowid共有18位组成,分成四个部分,每个部分分别有:6—3—6—3位;我们看一个示例:
SQL> select tt.*, rowid from tt;
        ID NAME                             ROWID
---------- -------------------------------- ------------------
         1 Nash                             AAAM0hAABAAAO3KAAA
         2 Bourne                           AAAM0hAABAAAO3KAAB

AAAM0h              AAB        AAAO3K    AAA
data_object_id    r_file_no  block_no  row_no

第一部分6位表示:该行数据所在的数据对象的 data_object_id
第二部分3位表示:该行数据所在的相对数据文件的id;
第三部分6位表示:该数据行所在的数据块的编号;
第四部分3位表示:该行数据的行的编号;
(后面我们会明白:索引就是保存了rowid后三个部分的信息。索引是物理存在的,而rowid是伪列。所以索引可以用来快速地定位到数据行。)

这里我们要注意将 data_object_id  object_id 区分开来,前者是oracle为它的每一个对象唯一分配的id,而后者与表tt对应的“段”有关,是存放表tt的段的id,也就是与存放表tt中数据的物理位置有关:
SQL> select owner,object_id,data_object_id,status from dba_objects where object_name='TT';
OWNER      OBJECT_ID   DATA_OBJECT_ID      STATUS
---------- ----------     --------------       -------
SYS         52513           52513            VALID
 
SQL> alter table tt move tablespace users;
Table altered.

SQL> select owner,object_id,data_object_id,status from dba_objects where object_name='TT';
OWNER      OBJECT_ID   DATA_OBJECT_ID      STATUS
---------- ----------     --------------       -------
SYS         52513            52514           VALID

我们看到当表tt move到了users表空间时,段发生了改变,物理位置发生了变化,从而 DATA_OBJECT_ID 也发生了变化。我们知道表是存放在“表段”中的,索引是存放在“索引段”中的。DATA_OBJECT_ID就是表示存放数据的“数据段对象的id”。

关于相对文件编码和绝对文件编号:
相对文件id是指相对于表空间,在表空间唯一,绝对文件是指相当于全局数据库而言的,全局唯一;
SQL> select file_name,file_id,relative_fno from dba_data_files;
FILE_NAME                                       FILE_ID    RELATIVE_FNO
--------------------------------------------    ---------- ------------
/u01/app/oracle/oradata/jiagulun/users01.dbf        4            4
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf       3            3
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf      2            2
/u01/app/oracle/oradata/jiagulun/system01.dbf       1            1
/u01/app/oracle/oradata/jiagulun/example01.dbf      5            5

2)rowid采用64进制来编码:
A ~ Z       a ~ z        0 ~ 9     +   /
0 ~ 25      26 ~ 51      52~61    62   63
编码方法是:A~Z表示0到25;a~z表示26到51;0~9表示52到61;+表示62;/表示63;刚好64个字符。
计算时可以参照下面的对照表:

我们演示一下具体的计算方法:
SQL> select tt.*, rowid from tt;
        ID NAME                             ROWID
---------- -------------------------------- ------------------
         1 Nash                             AAAM0iAAEAAAAGEAAA
         2 Bourne                           AAAM0iAAEAAAAGEAAB
表 tt 的 data_object_id 为 AAAM0iAAEAAAAGEAAA 的前6位:AAAM0i,那么我们来计算一下 AAAM0i 的值到底是多少:
AAAM0i = 12 * 64 * 64 + 14 * 64 + 34 = select 12 * 64 * 64 + 52 * 64 + 34 from dual = 52514
(注:A = 0;M = 12;0 = 52;i = 34)

然后我们查询字典表,看两种方法得到的值是否相等:
SQL> select data_object_id from dba_objects where object_name='TT';
DATA_OBJECT_ID
--------------
         52514
我们看到通过rowid计算得到的data_object_id和通过字典表查到的值相等!

表 tt 的相对文件编号为 AAAM0iAAEAAAAGEAAA 的中的 AAE,显然查表可知 AAE = 4;

我们在再来查询字典表:
SQL> select file_name, relative_fno from dba_data_files;
FILE_NAME                                          RELATIVE_FNO
-----------------------------------------------     ------------
/u01/app/oracle/oradata/jiagulun/users01.dbf             4
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf            3
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf           2
/u01/app/oracle/oradata/jiagulun/system01.dbf            1
/u01/app/oracle/oradata/jiagulun/example01.dbf           5
可以看到字典表显示relative_fno为4的数据文件为users01.dbf,
而我们前面执行过:alter table tt move tablespace users; 所以两种方式得到的结果是一致的。

表 tt 中的第一行数据存放的block的编号为 AAAM0iAAEAAAAGEAAA 中的 AAAAGE,而AAAAGE=6*64+4=388
表 tt 中的第一行数据存放的行的编号为 AAAM0iAAEAAAAGEAAA 中的 AAA,显然值为0,即第一行。

我们也可以通过Oracle提供的存储过程来计算出上面的值:
SQL> select dbms_rowid.rowid_object(rowid) data_object_id, dbms_rowid.rowid_relative_fno(rowid) relative_fno, dbms_rowid.rowid_block_number(rowid) block_no, dbms_rowid.rowid_row_number(rowid) row_no from tt;

DATA_OBJECT_ID RELATIVE_FNO   BLOCK_NO     ROW_NO
-------------- ------------ ---------- ----------
         52514            4        388          0
         52514            4        388          1
显然这个结果和我们手动计算的结果是一致的。

阅读(5039) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~