Oracle rowid 詳解

ylfxml發表於2011-05-16

本文討論的是關於oracle從8i開始引進object的概念後的rowid,即擴充套件(extended)的rowid:

Oracle6,ROWID中僅用6 bit代表檔案號
Oracle8,ROWID組成擴充套件為:FFFF.BBBBBBBB.RRRR,佔用6個位元組(其中10 bit file# + 22bit block# + 16bit row#);

1. rowid的介紹

先對rowid有個感官認識:

SQL> select ROWID from Bruce_test where rownum<2;

ROWID
------------------ ----------
AAABnlAAFAAAAAPAAA

ROWID的格式如下:

資料物件編號 檔案編號 塊編號 行編號
OOOOOO FFF BBBBBB RRR

我們可以看出,從上面的rowid可以得知:
AAABnl 是資料物件編號
AAF是相關檔案編號(檔案號就是0+0+5=5)
AAAAAP是塊編號
AAA 是行編號

怎麼依據這些編號得到具體的十進位制的編碼值呢,這是經常遇到的問題。這裡需要明白rowid的是基於64位編碼的18個字元顯示(資料物件編號(6) +檔案編號(3) +塊編號(6)+ 行編號(3)=18位),其中
A-Z <==> 0 - 25 (26)
a-z <==> 26 - 51 (26)
0-9 <==> 52 - 61 (10)
+/ <==> 62 - 63 (2)

共64位,明白這個後,就可以計算出10進位制的編碼值,計算公式如下:
d * (b ^ p)
其中:b就是基數,這裡就是64,p就是從右到左,已0開始的位置數
比如:上面的例子
檔案號AAF,具體的計算應該是:
5*(64^0)=5;
0*(64^1)=0;
0*(64^2)=0;
檔案號就是0+0+5=5
剛才提到的是rowid的顯示方式:基於64位編碼的18個字元顯示,其實rowid的儲存方式是:10 個位元組即80位儲存,其中資料物件編號需要32 位,相關檔案編號需要10 位,塊編號需要22,位行編號需要16 位,由此,我們可以得出:
32bit的object number,每個資料庫最多有4G個物件(2^32)
10bit的file number,每個物件最多有1022個檔案(2個檔案預留)(2^10)
22bit的block number,每個檔案最多有4M個BLOCK(2^22)
16bit的row number,每個BLOCK最多有64K個ROWS(2^16)

每表空間最大檔案數量--2^10=1024,去掉全0和全1,通常為1022個。
每資料檔案大小----------2^22=4M Blok,通常每個檔案最大Block數量為4MOracle塊。
對於大檔案表空間,最大能夠容納2^32=4GBlock。如果block_size32k,大檔案表空間最大容量可以達到4Gx32K=128T
每個Block中的行數----2^16=65536,通常每個Block最多隻能容納65536條記錄。

2. rowid相關的有用的sql

最簡單的基於rowid的顯示方式得到的響應的64位編碼對應值的sql:
select rowid ,
substr(rowid,1,6) "OBJECT",
substr(rowid,7,3) "FILE",
substr(rowid,10,6) "BLOCK",
substr(rowid,16,3) "ROW"
from TableName;

OWID OBJECT FILE BLOCK ROW
------------------ ------------ ------ ------------ ------
AAABc4AADAAAGLUAAA AAABc4 AAD AAAGLU AAA
AAABc4AADAAAGLUAAB AAABc4 AAD AAAGLU AAB
AAABc4AADAAAGLUAAC AAABc4 AAD AAAGLU AAC
AAABc4AADAAAGLUAAD AAABc4 AAD AAAGLU AAD
AAABc4AADAAAGLUAAE AAABc4 AAD AAAGLU AAE

透過dbms_rowid這個包,可以直接的得到具體的rowid包含的資訊:

select 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 bruce_t where rownum<5;

OBJECT_ID FILE_ID BLOCK_ID NUM
---------- ---------- ---------- ----------
5944 3 25300 0
5944 3 25300 1
5944 3 25300 2
5944 3 25300 3

一些使用ROWID的函式
ROWIDTOCHAR(rowid) :將ROWID轉換成STRING
CHARTOROWID('rowid_string') :將STRING轉換成ROWID

另外,就是自己寫的一些函式:(下面的函式是網友eygle提供)

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 get_rowid(rowid), name from bruce_t;
GET_ROWID(ROWID) NAME

-------------------------------------------------------------------------------- --------------------------------
Object# is :5944 BruceLau
Relative_fno is :3
Block number is :25300
Row number is :0
Object# is :5944 MabelTang
Relative_fno is :3
Block number is :25300
Row number is :1

[@more@]oracel

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7548/viewspace-1049941/,如需轉載,請註明出處,否則將追究法律責任。

相關文章