Oracle rowid詳解

Oracle中的ROWID是數據的物理地址。一個ROWID包含關於文件、塊和該塊中的行的一行信息。ROWID還包含其它數據,如相關文件數和OBJECT_ID。php


   ROWID能夠分爲物理rowid和邏輯rowid兩種。普通的堆表中的rowid是物理rowid,索引組織表(IOT)的rowid是邏輯rowid。oracle提供了一種urowid的數據類型,同時支持物理和邏輯rowid。本文主要關注物理rowid。數據庫

   物理rowid又分爲擴展rowid(extended rowid)和限制rowid(restricted rowid)兩種格式。限制rowid主要是oracle7之前的rowid格式,如今已經再也不使用,保留該類型只是爲了兼容性。因此本文的提到物理rowid通常是指擴展rowid格式。  oracle

1.Rowid的顯示形式ide

咱們從rowid僞列裏select出來的rowid是基於base64編碼,一共有18位,分爲4部分:post

OOOOOOFFFBBBBBBRRR編碼

其中:spa

OOOOOO:六位表示data object id,根據object id能夠肯定segment。關於data object id和object id的區別,請參考http://www.orawh.com/index.php/archives/62.net

FFF:三位表示相對文件號。根據該相對文件號能夠獲得絕對文件號,從而肯定datafile。關於相對文件號和絕對文件號,請參考http://blog.itpub.net/post/330/22749rest

BBBBBB:六位表示data block number。這裏的data block number是相對於datafile的編號,而不是相對於tablespace的編號。視頻

RRR:三位表示row number。


Oracle提供了dbm_rowid來進行rowid的一些轉換計算。


SQL> create table test(id int,name varchar2(30));

Table created.

SQL> insert into test values(1,'a');

1 row created.

SQL> commit;

Commit complete.

SQL> select rowid from test;

ROWID

------------------

AAAGbEAAHAAAAB8AAA

SQL> select dbms_rowid.rowid_object(rowid) obj#,

2 dbms_rowid.rowid_relative_fno(rowid) rfile#,

3 dbms_rowid.rowid_block_number(rowid) block#,

4 dbms_rowid.rowid_row_number(rowid) row#,

5 dbms_rowid.rowid_to_absolute_fno(rowid,'SYS','TEST') file#

6 from test;

OBJ# RFILE# BLOCK# ROW# FILE#

----------- ------------ ------------- ---------- ----------

26308 7 124 0 7

2. 如何從rowid計算獲得obj#,rfile#,block#,row#

rowid是base64編碼的,用A~Z a~z 0~9 + /共64個字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63能夠將其看作一個64進制的數。

因此,

obj#=AAAGbE=6*64^2+27*64+4=26308

rfile#=AAH=7

block#=AAAAB8=64+60=124

row#=AAA=0

3. 如何從obj#,rfile#,block#,row#計算獲得rowid

實際上就是將十進制數轉化成64進制數,固然,從二進制轉化的規則比較簡單點。

將二進制數從右到左,6個bit一組,而後將這6個bit組轉成10進制數,就是A~Z a~z 0~9 + /這64個字符的位置(從0開始),替換成base64的字符便可。

obj#=26308=110 011011 000100=6 27 4=G b E,補足成6位base64編碼,左邊填0,也就是A,結果爲AAAGbE

rfile#=7=111=7=H,補足成3位,獲得AAH

block#=124=1 111100=1 60=B 8,補足成6位,獲得AAAAB8

row#=0,3位AAA

合起來就是AAAGbEAAHAAAAB8AAA

4. Rowid的內部存儲格式

雖然咱們從rowid僞列中select出來的rowid是以base64字符顯示的,但在oracie內部存儲的時候仍是以原值的二進制表示的。一個擴展rowid採用10個byte來存儲,共80bit,其中obj#32bit,rfile#10bit,block#22bit,row#16bit。因此相對文件號不能超過1023,也就是一個表空間的數據文件不能超過1023個(不存在文件號爲0的文件),一個datafile只能有2^22=4M個block,,一個block中不能超過2^16=64K行數據。而一個數據庫內不能有超過2^32=4G個object。

SQL> select dump(rowid,16) from test;

DUMP(ROWID,16)

--------------------------------------------

Typ=69 Len=10: 0,0,66,c4,1,c0,0,7c,0,0

00000000 00000000 01100110 11000100 00000001 11000000 00000000 01111100 00000000 00000000

最右邊16bit爲row#=00000000 00000000=0

接下來22bit爲block#=000000 00000000 01111100=124

接下來10bit爲rfile#=00000001 11=7

接下來32bit爲obj#=00000000 00000000 01100110 11000100=26308

5. Index中存儲的rowid

a. 普通B-tree索引

SQL> create index ix_test on test(id);

Index created.

SQL> select file_id,block_id from dba_extents where segment_name='IX_TEST' and owner=user;

FILE_ID BLOCK_ID

---------- ----------

7 129

---因爲是assm表空間,去掉3個block的頭

SQL> alter system dump datafile 1 block 132;

System altered.

獲得trace文件內容以下(省略無關內容):

row#0[8024] flag: -----, lock: 0

col 0; len 2; (2): c1 02 ---索引鍵數據ID=1

col 1; len 6; (6): 01 c0 00 7c 00 00 ---對應的rowid記錄

----- end of leaf block dump -----

End dump data blocks tsn: 7 file#: 7 minblk 132 maxblk 132

普通索引中保存的rowid是不包括obj#的,可是分區表的global index是包括obj#的,這是由於分區表包括多個segment,每一個segment可能在不一樣的datafile中,根據表的obj#就沒法肯定該索引鍵對應的rowid(rfile#肯定不了)。

01 c0 00 7c 00 00 轉化爲二進制 000000001 11000000 00000000 01111100 00000000 00000000

右邊8bit row#=0

接下來22bit block#=000000 00000000 01111100=124

接下來10bit rfile#=000000001 11=7

b.惟一索引

SQL> drop index ix_test;

Index dropped.

SQL> create unique index ix_test on test(id);

Index created.

SQL> select file_id,block_id from dba_extents where segment_name='IX_TEST' and owner=user;

FILE_ID BLOCK_ID

---------- ----------

7 129

SQL> alter system dump datafile 1 block 132;

System altered.

獲得trace文件內容以下:

row#0[8025] flag: -----, lock: 0, data:(6): 01 c0 00 7c 00 00 ---對應的rowid記錄

col 0; len 2; (2): c1 02 ---索引鍵數據ID=1

----- end of leaf block dump -----

End dump data blocks tsn: 7 file#: 7 minblk 132 maxblk 132

獲得rowid爲 01 c0 00 7c 00 00,具體的轉換計算和前面的同樣,就不重複了。


oracle視頻教程請關注:http://down.51cto.com/4202939/up

相關文章
相關標籤/搜索