解析Oracle rowid系列一
搞Oracle的人,都知道表里有一个叫做rowid的伪列,也知道可以通过rowid来快速定位表里的记录,至少通过oracle的索引来快速查找表里的数据就是通过rowid来定位的。可是,我们真的对rowid很了解吗?至少,我之前存在了一些误区,甚至有点儿荒谬!在此,对rowid作一个全面解析,同大家分享,以飨网友。
1 Oracle rowid格式:
| rowid | OOOOOO | FFF | BBBBBB | RRR |
| 说明 |
数据对象号
|
相对文件号 | 数据块号 | 行号 |
上述表格是Oracle 9i及以上版本数据库中的rowid格式:6位对象号+3位相对文件号+6位数据块号+3位行号,是一个18位的64进制值。这个18位的64进制值在数据库内却是以10个bytes合计80个bit的二进制数存放的,和我们直接看到的结果有所区别。这里的64进制和10进制的对应编码如下表:
| 64进制编码 | A | B | … | Z | a | b | … | z | 0 | 1 | … | 9 | + | / |
| 10进制值 | 0 | 1 | … | 25 | 26 | 27 | … | 51 | 52 | 53 | … | 61 | 62 | 63 |
2 那么这个18位的64进制值又是如何同80位的二进制数对应的呢?其中,6位的对象号在数据库中是用32位二进制来存放的,也就意味着一个oracle数据库中最多可以有232个对象,即4G个对象;3位的相对文件号在数据库中是用10位二进制来存放的,也就意味着一个表空间中最多可以容纳210=1024去掉全0和全1个数据文件,即1022个数据文件;6位的数据块号用22位二进制来存放的,也就意味着一个数据文件最多可以包含222=4M个数据块;3位的行号在数据库中是用16位二进制来存放的,也就意味着一个数据块上最多可以容纳216=65536行记录。
3 我们已经对rowid有了基本认识,我们又该如何获取rowid呢?见下例:
SQL> show user;
USER is “HR”
SQL> select employee_id,last_name,rowid from employees where employee_id=100;
EMPLOYEE_ID LAST_NAME ROWID
———– ————————- ——————
100 King AAAR5pAAFAAAADPAAA
SQL>
我们可以在查询列表中,把rowid伪列当做普通的字段来查询。上例中,AAAR5p就是HR.employees在数据库中的对象号,AAF表示相对文件号,AAAADP则表示数据块编号,最后的3个AAA则表示行号。当然,我们完全可以根据上述的转换表,将这些64进制值直接转成对应的10进制值。分别就是HR.employees表在数据库内的对象号是73321,而该表在数据库内部是存放在第5号文件(AAF=0*642+0*641+5*640=5)上的,employee_id=100的记录则是放在第5号文件的第207个数据块上的;最后的AAA表示该记录是位于第5号文件上的第207个数据块上的第1条记录。
4 除了上述方法,我们还可以通过数据库提供给我们的工具包来获取该信息:
SQL> select rowid,
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 rowidtochar(rowid) from employees where employee_id=100
7 ;
ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ROWIDTOCHAR(ROWID)
—————— ———- ———- ———- ———- ——————
AAAR5pAAFAAAADPAAA 73321 5 207 0 AAAR5pAAFAAAADPAAA
SQL>
很显然,我们通过调用系统的dbms_rowid包,获得的rowid信息同我们手工将64进制转成10进制得到的结果完全一致!
这是探讨Oracle rowid系列之一,后续将有系列二探讨Cluster table rowid、系列三探讨Bigfile tablespace rowid,敬请关注。
From OracleOnLinux, post 解析Oracle rowid系列一
Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically to your feed reader.
Comments
请教了,这段~~~那么这个18位的64进制值又是如何同80位的二进制数对应的呢?其中,6位的对象号在数据库中是用32位二进制来存放的,也就意味着一个oracle数据库中最多可以有232个对象,即4G个对象;3位的相对文件号在数据库中是用10位二进制来存放的,也就意味着一个表空间中最多可以容纳210=1024去掉全0和全1个数据文件,即1022个数据文件;6位的数据块号用22位二进制来存放的,也就意味着一个数据文件最多可以包含222=4M个数据块;3位的行号在数据库中是用16位二进制来存放的,也就意味着一个数据块上最多可以容纳216=65536行记录。~~~
其中的比如计算对象个数和计算文件个数的2^32和2^10中的:
32与6位对象号的6
10与3位相对文件号的3
怎么关联计算的?

[...] 在解析Oracle rowid系列一里,我们简单探讨了Oracle rowid的格式及获取rowid的方法,在本篇中我们探讨的主题是:通过Oracle rowid真的可以唯一定位到表的一条记录吗?或者说在同一Oracle数据库中,rowid就一定唯一没有重复的吗? 实验步骤: 1 构建cluster table并插入测试数据: [...]