rowid的组成

来源:互联网 发布:剑灵秦义绝捏脸数据图 编辑:程序博客网 时间:2024/05/29 08:30

 
rowid就像是记录的详细地址,想要寻找记录就需要通过这个详细地址去寻找。
rowid存储在索引中而不是在表中。
我们可以通过以下包通过rowid找到文件号,块号,行号。
dbms_rowid.rowid_relative_fno    -- 文件号
dbms_rowid.rowid_block_number  --块号
dbms_rowid.rowid_row_number   --行号
 

SQL> select banner from v$version;BANNER--------------------------------------------------------------------------------Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit ProductionPL/SQL Release 12.2.0.1.0 - ProductionCORE        12.2.0.1.0        ProductionTNS for Linux: Version 12.2.0.1.0 - ProductionNLSRTL Version 12.2.0.1.0 - Production SQL>  select rowid,dbms_rowid.rowid_relative_fno(rowid)  fno,dbms_rowid.rowid_block_number(rowid) bno   from liu.test;ROWID                          FNO             BNO------------------ ---------- ----------AAAR3sAAMAAAACGAAA           12             134

liu.test表插入了一行测试数据,我们先找到该行记录的rowid,fno(relative file id),bno(block id)
rowid由对象号,数据文件号,块号,行号构成。
然后我们通过base64表将rowid分解转化成十进制
1-6位,对象号:AAAR3s-->0 0 0 1755 44 -->0*64^5+0*64^4+0*64^3+17*64^2+55*64^1+44*64^0=73196 
7-9位,数据文件号:AAM-->0 0 12 -->0*64^2+0*64^1+12*64^0=12 (对应fno)
10-15位,块号:AAAACG-->00 0 2 6-->0*64^5+0*64^4+0*64^3+0*64^2+2*64^1+6*64^0=134 (对应bno)
16-18位,行号:AAA--> 0 0 0--> ...=0

 
base64转换表:

索引
对应字符
索引
对应字符
索引
对应字符
索引
对应字符
0
A
17
R
34
i
51
z
1
B
18
S
35
j
52
0
2
C
19
T
36
k
53
1
3
D
20
U
37
l
54
2
4
E
21
V
38
m
55
3
5
F
22
W
39
n
56
4
6
G
23
X
40
o
57
5
7
H
24
Y
41
p
58
6
8
I
25
Z
42
q
59
7
9
J
26
a
43
r
60
8
10
K
27
b
44
s
61
9
11
L
28
c
45
t
62
+
12
M
29
d
46
u
63
/
13
N
30
e
47
v
  
14
O
31
f
48
w
  
15
P
32
g
49
x
  
16
Q
33
h
50
y
  



现在数据文件号,块号都对应了,我们来查找对象号
SQL> select owner,object_name,object_id from dba_objects where object_name = 'TEST';OWNER           OBJECT_NAME                           OBJECT_ID---------- ------------------------------ ----------LIU           TEST                                73196


对象号也对应了
 
行号为0,是否每一行+1,从0开始呢。我们再插入数据进行验证
循环插入50w行数据
beginfor i in 1..500000loopinsert into liu.test values(i);end loop;commit;end;/SQL> select count(1) from liu.test;  COUNT(1)----------    500001SQL> select * from (select rowid from liu.test order by  a asc) where rownum<=5;ROWID------------------AAAR3sAAMAAAACGAAAAAAR3sAAMAAAACGAABAAAR3sAAMAAAACGAACAAAR3sAAMAAAACGAADAAAR3sAAMAAAACGAAE


可以看出,当行号是持续递增的,0表示第一行,1表示第二行以此类推
但是这里会有一个问题,行号有最大值--///,也就是说每个块只能存储AAA--///的数据,也就是0--63*64^2+63*64^1+63*64^0,也就是64^3=262144行。
但是oracle并没有使用所有的basic64编码号
select a,rowid from liu.test where rowid like 'AAAR3sAAMAAAACG___' order by rowid asc;...         A ROWID---------- ------------------       649 AAAR3sAAMAAAACGAKJ       650 AAAR3sAAMAAAACGAKK       651 AAAR3sAAMAAAACGAKL       652 AAAR3sAAMAAAACGAKM       653 AAAR3sAAMAAAACGAKN       654 AAAR3sAAMAAAACGAKO       655 AAAR3sAAMAAAACGAKP       656 AAAR3sAAMAAAACGAKQ       657 AAAR3sAAMAAAACGAKR       658 AAAR3sAAMAAAACGAKS       659 AAAR3sAAMAAAACGAKT 660 rows selected.select a,rowid from liu.test where rowid like 'AAAR3sAAMAAAACH___' order by rowid asc;...         A ROWID---------- ------------------      1309 AAAR3sAAMAAAACHAKJ      1310 AAAR3sAAMAAAACHAKK      1311 AAAR3sAAMAAAACHAKL      1312 AAAR3sAAMAAAACHAKM      1313 AAAR3sAAMAAAACHAKN      1314 AAAR3sAAMAAAACHAKO      1315 AAAR3sAAMAAAACHAKP      1316 AAAR3sAAMAAAACHAKQ      1317 AAAR3sAAMAAAACHAKR      1318 AAAR3sAAMAAAACHAKS      1319 AAAR3sAAMAAAACHAKT 660 rows selected.


事实并非我们想象的那样,每个块最多存放660行数据。这也是有道理的,因为oracle块的大小是固定的,比如8k,那么他的行数不可能非常的高。
那么再看看660行发生了什么
SQL> select t1.rid from  (select rowid rid,rownum rn from liu.test order by  a asc)t1 where t1.rn>=658 and t1.rn<=662;RID------------------AAAR3sAAMAAAACDAKRAAAR3sAAMAAAACDAKSAAAR3sAAMAAAACDAKTAAAR3sAAMAAAACEAAAAAAR3sAAMAAAACEAAB
当行到AKT时,块号+1,行号从0开始计算。
 
总结:
1.rowid记录了行记录的物理存放位置,通过basic64编码或者dbms_rowid转换转换rowid找到那个位置
2.每个块最多存放660行记录,当插入数据时要超过水位线的时候便把数据插入到下一个块
 
 

原创粉丝点击