【转】oracle中rowid的用法 (全面)
ROWID是數(shù)據(jù)的詳細(xì)地址,通過(guò)rowid,oracle可以快速的定位某行具體的數(shù)據(jù)的位置。
ROWID可以分為物理rowid和邏輯rowid兩種。普通的堆表中的rowid是物理rowid,索引組織表(IOT)的rowid是邏輯rowid。oracle提供了一種urowid的數(shù)據(jù)類型,同時(shí)支持物理和邏輯rowid。本文主要關(guān)注物理rowid
物理rowid又分為擴(kuò)展rowid(extended rowid)和限制rowid(restricted rowid)兩種格式。限制rowid主要是oracle7以前的rowid格式,現(xiàn)在已經(jīng)不再使用,保留該類型只是為了兼容性。所以本文的提到物理rowid一般是指擴(kuò)展rowid格式。
本文主要內(nèi)容:
1.Rowid的顯示形式
2.如何從rowid計(jì)算得到obj#,rfile#,block#,row#
3.如何從obj#,rfile#,block#,row#計(jì)算得到rowid
4.Rowid的內(nèi)部存儲(chǔ)格式
5.Index中存儲(chǔ)的rowid
1.Rowid的顯示形式
我們從rowid偽列里select出來(lái)的rowid是基于base64編碼,一共有18位,分為4部分:
OOOOOOFFFBBBBBBRRR
其中:
OOOOOO: 六位表示data object id,根據(jù)object id可以確定segment。關(guān)于data object id和object id的區(qū)別,請(qǐng)參考http://www.orawh.com/index.php/archives/62
FFF: 三位表示相對(duì)文件號(hào)。根據(jù)該相對(duì)文件號(hào)可以得到絕對(duì)文件號(hào),從而確定datafile。關(guān)于相對(duì)文件號(hào)和絕對(duì)文件號(hào),請(qǐng)參考http://blog.itpub.net/post/330/22749
BBBBBB:六位表示data block number。這里的data block number是相對(duì)于datafile的編號(hào),而不是相對(duì)于tablespace的編號(hào)。
RRR:三位表示row number。
Oracle提供了dbm_rowid來(lái)進(jìn)行rowid的一些轉(zhuǎn)換計(jì)算。
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計(jì)算得到obj#,rfile#,block#,row#
rowid是base64編碼的,用A~Z a~z 0~9 + /共64個(gè)字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63可以將其看做一個(gè)64進(jìn)制的數(shù)。
所以,
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#計(jì)算得到rowid
實(shí)際上就是將十進(jìn)制數(shù)轉(zhuǎn)化成64進(jìn)制數(shù),當(dāng)然,從二進(jìn)制轉(zhuǎn)化的規(guī)則比較簡(jiǎn)單點(diǎn)。
將二進(jìn)制數(shù)從右到左,6個(gè)bit一組,然后將這6個(gè)bit組轉(zhuǎn)成10進(jìn)制數(shù),就是A~Z a~z 0~9 + /這64個(gè)字符的位置(從0開(kāi)始),替換成base64的字符即可。
obj#=26308=110 011011 000100=6 27 4=G b E,補(bǔ)足成6位base64編碼,左邊填0,也就是A,結(jié)果為AAAGbE
rfile#=7=111=7=H,補(bǔ)足成3位,得到AAH
block#=124=1 111100=1 60=B 8,補(bǔ)足成6位,得到AAAAB8
row#=0,3位AAA
合起來(lái)就是AAAGbEAAHAAAAB8AAA
4. Rowid的內(nèi)部存儲(chǔ)格式
雖然我們從rowid偽列中select出來(lái)的rowid是以base64字符顯示的,但在oracie內(nèi)部存儲(chǔ)的時(shí)候還是以原值的二進(jìn)制表示的。一個(gè)擴(kuò) 展rowid采用10個(gè)byte來(lái)存儲(chǔ),共80bit,其中obj#32bit,rfile#10bit,block#22bit,row#16bit。所以相對(duì)文件號(hào)不能超過(guò)1023,也就是一個(gè)表空間的數(shù)據(jù)文件不能超過(guò)1023個(gè)(不存在文件號(hào)為0的文件),一個(gè)datafile只能有2^22=4M個(gè) block,,一個(gè)block中不能超過(guò)2^16=64K行數(shù)據(jù)。而一個(gè)數(shù)據(jù)庫(kù)內(nèi)不能有超過(guò)2^32=4G個(gè)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
接下來(lái)22bit為block#=000000
00000000 01111100=124
接下來(lái)10bit為rfile#=00000001
11=7
接下來(lái)32bit為obj#=00000000
00000000 01100110 11000100=26308
5. Index中存儲(chǔ)的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個(gè)block的頭
SQL> alter system dump datafile 1 block 132;
System altered.
得到trace文件內(nèi)容如下(省略無(wú)關(guān)內(nèi)容):
row#0[8024] flag: -----, lock: 0
col 0; len 2; (2): c1 02 ---索引鍵數(shù)據(jù)ID=1
col 1; len 6; (6): 01 c0 00 7c 00 00 ---對(duì)應(yīng)的rowid記錄
----- end of leaf block dump -----
End dump data blocks tsn: 7 file#: 7 minblk 132 maxblk 132
普通索引中保存的rowid是不包括obj#的,但是分區(qū)表的global index是包括obj#的,這是因?yàn)榉謪^(qū)表包括多個(gè)segment,每個(gè)segment可能在不同的datafile中,根據(jù)表的obj#就無(wú)法確定該 索引鍵對(duì)應(yīng)的rowid(rfile#確定不了)。
01 c0 00 7c 00 00 轉(zhuǎn)化為二進(jìn)制 000000001
11000000 00000000 01111100 00000000 00000000
右邊8bit row#=0
接下來(lái)22bit block#=000000 00000000
01111100=124
接下來(lái)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文件內(nèi)容如下:
row#0[8025] flag: -----, lock: 0, data:(6): 01 c0 00 7c
00 00 ---對(duì)應(yīng)的rowid記錄
col 0; len 2; (2): c1 02 ---索引鍵數(shù)據(jù)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,具體的轉(zhuǎn)換計(jì)算和前面的一樣,就不重復(fù)了。
Base64編碼說(shuō)明
Base64編碼要求把3個(gè)8位字節(jié)(3*8=24)轉(zhuǎn)化為4個(gè)6位的字節(jié)(4*6=24),之后在6位的前面補(bǔ)兩個(gè)0,形成8位一個(gè)字節(jié)的形式。 如果剩下的字符不足3個(gè)字節(jié),則用0填充,輸出字符使用'=',因此編碼后輸出的文本末尾可能會(huì)出現(xiàn)1或2個(gè)'='。
為了保證所輸出的編碼位可讀字符,Base64制定了一個(gè)編碼表,以便進(jìn)行統(tǒng)一轉(zhuǎn)換。編碼表的大小為2^6=64,這也是Base64名稱的由來(lái)。
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 |
/ |
原文鏈接:http://hi.baidu.com/wwynhm/item/1a376fbc6063b7d084dd79a7
總結(jié)
以上是生活随笔為你收集整理的【转】oracle中rowid的用法 (全面)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《三角洲行动》凯席尔瓦干员介绍
- 下一篇: 电脑怎么投屏到电视如何电脑投屏到电视机