Oracle中rowid的用法
ROWID可以分為物理rowid和邏輯rowid兩種。普通的堆表中的rowid是物理rowid,索引組織表(IOT)的rowid是邏輯rowid。oracle提供了一種urowid的資料型別,同時支援物理和邏輯rowid。本文主要關注物理rowid
物理rowid又分為擴充套件rowid(extended rowid)和限制rowid(restricted rowid)兩種格式。限制rowid主要是oracle7以前的rowid格式,現在已經不再使用,保留該型別只是為了相容性。所以本文的提到物理rowid一般是指擴充套件rowid格式。
本文主要內容:
1.Rowid的顯示形式
2.如何從rowid計算得到obj#,rfile#,block#,row#
3.如何從obj#,rfile#,block#,row#計算得到rowid
4.Rowid的內部儲存格式
5.Index中儲存的rowid
1.Rowid的顯示形式
我們從rowid偽列裡select出來的rowid是基於base64編碼,一共有18位,分為4部分:
OOOOOOFFFBBBBBBRRR
其中:
OOOOOO: 六位表示data object id,根據object id可以確定segment。關於data object id和object id的區別,請參考
FFF: 三位表示相對檔案號。根據該相對檔案號可以得到絕對檔案號,從而確定datafile。關於相對檔案號和絕對檔案號,請參考http://blog.itpub.net/post/330/22749
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,具體的轉換計算和前面的一樣,就不重複了。
Base64編碼說明
Base64編碼要求把3個8位位元組(3*8=24)轉化為4個6位的位元組(4*6=24),之後在6位的前面補兩個0,形成8位一個位元組的形式。 如果剩下的字元不足3個位元組,則用0填充,輸出字元使用'=',因此編碼後輸出的文字末尾可能會出現1或2個'='。
為了保證所輸出的編碼位可讀字元,Base64制定了一個編碼表,以便進行統一轉換。編碼表的大小為2^6=64,這也是Base64名稱的由來。
Base64編碼表
碼值 | 字元 | 碼值 | 字元 | 碼值 | 字元 | 碼值 | 字元 | |||
---|---|---|---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28878983/viewspace-2135873/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【oracle中rowid的用法】Oracle
- oracle中的Rowid和UrowidOracle
- oracle中rownum和rowid的區別Oracle
- Oracle中with的用法Oracle
- oracle 表中的rowid是什麼意思Oracle
- 【ROWID】Oracle rowid說明Oracle
- oracle rowidOracle
- Oracle中rownum與rowid使用上的問題Oracle
- 【 Oracle中rownum的用法 】Oracle
- Oracle 中 case的用法Oracle
- MySQL中的_rowidMySql
- oracle rowid 的含義Oracle
- ORACLE ROWID (zt)Oracle
- oracle樹中prior的用法Oracle
- oracle中copy from的用法Oracle
- oracle中top用法Oracle
- Oracle中group by用法Oracle
- oracle常用包之dbms_rowid oracle rowid含義分析Oracle
- oracle rowid詳解Oracle
- Oracle rowid 詳解Oracle
- Oracle ROWID-1Oracle
- Oracle ROWID-2Oracle
- oracle rowid (轉載)Oracle
- Oracle中select ... for update的用法Oracle
- 案例:oracle中case when的用法Oracle
- oracle8的ROWID結構Oracle
- Oracle中"cascade"的用法總結Oracle
- Oracle中的ROWID實現(r10筆記第95天)Oracle筆記
- 淺談Rowid中的行號
- oracle壞塊的rowid方式修復Oracle
- oracle8的ROWID結構(轉)Oracle
- oracle中substr() instr() 用法Oracle
- oracle中merge into用法解析Oracle
- Oracle PL/SQL中EXCEPTION用法OracleSQLException
- ORACLE 中ROWNUM用法總結!Oracle
- ORACLE 中ROWNUM用法總結Oracle
- oracle中的CURRVAL和NEXTVAL用法Oracle
- oracle中的exists 和not exists 用法詳解Oracle