oracle rowid

搞oracle的人都很清楚rowid这个东西,rowid就是唯一标志记录物理位置的一个id,在oracle 8版本以前,rowid由file#+block#+row#组成,占用6个bytes的空间,10 bit 的 file# ,22bit 的 block# ,16 bit 的 row#。
 
从oracle 8开始rowid变成了extend rowid,由data_object_id#+rfile#+block#+row#组成,占用10个bytes的空间, 32bit的 data_object_id#,10 bit 的 rfile#,22bit 的 block#,16 bit 的 row#.由于rowid的组成从file#变成了rfile#,所以数据文件数的限制也从整个库不能超过1023个变成了每个表空间不能超过1023个数据文件。
 
 
说了rowid的组成,那么我们再来看看rowid在索引里面占用的字节数又是什么样子的。在oracle 8以前索引中存储的rowid占用字节数也是6bytes,在oracle8之后,虽然oracle使用了extend rowid,但是在普通索引里面依然存储了bytes的rowid,只有在global index中存储的是10bytes的extend rowid,而extend rowid也是global index出现的一个必要条件,下面我们会解释原因。
 
 
为什么golbal index需要把data_object_id#也包含在index rowid entry中呢?如果不包含会这么样?首先我们需要知道index的rowid entry的存在是为了能根据它找到表的这条记录存在哪个具体的物理位置,我们需要知道它在哪个数据文件,在哪个block,在那一行,普通的索引oracle根据rfile#,block#,row#就可以知道了,但是partition table可以分布在多个表空间,也就是可以分布在多个数据文件,当我们建立local index时,index rowid entry并不包含data_object_id#,因为oracle可以知道这个index对应的是哪一个table分区,并可以得到table分区的ts#(tablespace号),那么oracle根据ts#和rfile#就可以找到具体的数据文件。但是如果换成是golbal index,如果不包含data_object_id#,那么我们并不能知道这个索引对应着哪个表分区,也自然不能知道它的rfile#和file#的转换关系,所以它将找不到所对应的记录。包含data_object_id#后,oracle可以根据data_object_id#实现rfile#和file#的转换然后找到记录对应的物理位置。需要注意的是要理解以上概念我们还是需要了解file#和rfile#的区别。
 
关于file#和rfile#的区别可以参考biti_rainy的一篇blog
 
继续上面的话题,我们猜想oracle实现rfile#和file#的转换是不是由一些递归sql来实现,所以我们做了一个测试来看是否oracle从file$等基表中实现呢?我们做了一个10046 trace,发现并不存在相应的递归sql,那oracle怎么实现呢?可能是直接取一些x$table中的数据了吧,那哪个x$table保留这些信息呢?
 
x$kccfe!!!
 
 
SQL 10G>desc x$kccfe  Name                                      Null?    Type  ----------------------------------------- -------- ----------------------------  ADDR                                               RAW(4)  INDX                                               NUMBER  INST_ID                                            NUMBER  FENUM                                              NUMBER  FECSZ                                              NUMBER  FEBSZ                                              NUMBER  FESTA                                              NUMBER  FECRC_SCN                                          VARCHAR2(16)  FECRC_TIM                                          VARCHAR2(20)  FECRC_THR                                          NUMBER  FECRC_RBA_SEQ                                      NUMBER  FECRC_RBA_BNO                                      NUMBER  FECRC_RBA_BOF                                      NUMBER  FECRC_ETB                                          RAW(132)  FECPS                                              VARCHAR2(16)  FECPT                                              VARCHAR2(20)  FECPC                                              NUMBER  FESTS                                              VARCHAR2(16)  FESTT                                              VARCHAR2(20)  FEBSC                                              VARCHAR2(16)  FEFNH                                              NUMBER  FEFNT                                              NUMBER  FEDUP                                              NUMBER  FEURS                                              VARCHAR2(16)  FEURT                                              VARCHAR2(20)  FEOFS                                              VARCHAR2(16)  FEONC_SCN                                          VARCHAR2(16)  FEONC_TIM                                          VARCHAR2(20)  FEONC_THR                                          NUMBER  FEONC_RBA_SEQ                                      NUMBER  FEONC_RBA_BNO                                      NUMBER  FEONC_RBA_BOF                                      NUMBER  FEONC_ETB                                          RAW(132)  FEPOR                                              NUMBER  FETSN                                              NUMBER  FETSI                                              NUMBER  FERFN                                              NUMBER  FEPFT                                              NUMBER  FEDOR                                              NUMBER  FEPDI                                              NUMBER  FEFDB                                              NUMBER  FEPLG_SCN                                          VARCHAR2(16)  FEPAX                                              NUMBER  FEFLG                                              NUMBER
 
从这个x$table中oracle可以实现file和rfile的转换。
 
 
最后我们来看一个例子
 
SQL 10G>desc test  Name                                      Null?    Type  ----------------------------------------- -------- ----------------------------  A                                                  NUMBER  B                                                  VARCHAR2(32)
 
test是一张分区表
 
SQL 10G>select table_name,partition_name,tablespace_name from dba_tab_partitions where table_name='TEST';
TABLE_NAME                     PARTITION_NAME                 TABLESPACE_NAME ------------------------------ ------------------------------ ------------------------------ TEST                           P1                             TESTROWID TEST                           P2                             TESTROWID
 
 
这条记录所在的物理位置
 
SQL 10G>select dbms_rowid.ROWID_OBJECT(rowid) data_object_id#,dbms_rowid.ROWID_RELATIVE_FNO(rowid) rfile#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block#,dbms_rowid.ROWID_ROW_NUMBER(rowid) row# from test ;
DATA_OBJECT_ID#     RFILE#     BLOCK#       ROW# --------------- ---------- ---------- ----------           63665         28         15          0
 
 
 
 
我们对它创建全局索引
 
SQL 10G>create index ind_test on test(a);  
Index created.
 
再创建本地索引
 
SQL 10G>create index ind_test_local on test(b) local;  
Index created.
 
 
SQL 10G>select dump(rowid,16) rid from test;
RID ---------------------------------------------------------------------------- Typ=69 Len=10: 0,0,f8,b1,7,0,0,f,0,0
 
去看看全局索引和本地索引中rowid entry的区别
 
SQL 10G>select header_block,header_file from dba_segments where segment_name='IND_TEST';
HEADER_BLOCK HEADER_FILE ------------ -----------         1403           4
 
 
SQL 10G>select header_block,header_file from dba_segments where segment_name='IND_TEST_LOCAL';
HEADER_BLOCK HEADER_FILE ------------ -----------           11          33           11          34
 
 
SQL 10G>ALTER SYSTEM DUMP DATAFILE 4 BLOCK 1404;
System altered.
 
 
SQL 10G>ALTER SYSTEM DUMP DATAFILE 33 BLOCK 12;
System altered.
 
 
全局索引ind_test的rowid entry
col 1; len 10; (10):  00 00 f8 b1 07 00 00 0f 00 00
 
 
本地索引ind_test_local的rowid entry
 
col 1; len 6; (6):  07 00 00 0f 00 00
 
可以看出本地索引存储了6bytes rowid,全局索引存储了10bytes rowid
 
再来看一下00 00 f8 b1 07 00 00 0f 00 00
转换成bit就是
00000000 00000000 11111000 10110001 00000111 00000000 00000000 00001111 00000000 00000000
 
32bit的 data_object_id#,10 bit 的 rfile#,22bit 的 block#,16 bit 的 row#.
 
00000000 00000000 11111000 10110001  data_object_id#
转换成10进制就是
 
2^15+2^14+2^13+2^12+2^11+2^7+2^5+2^4+2^0=63665
 
00000111 00 rfile#
 
2^4+2^3+2^2=28 
0000000000000000001111  block#
 
2^3+2^2+2^1+2^0=15
 
0000000000000000 rowi#
 
0
 
SQL 10G>select dbms_rowid.ROWID_OBJECT(rowid) data_object_id#,dbms_rowid.ROWID_RELATIVE_FNO(rowid) rfile#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block#,dbms_rowid.ROWID_ROW_NUMBER(rowid) row# from test ;
DATA_OBJECT_ID#     RFILE#     BLOCK#       ROW# --------------- ---------- ---------- ----------           63665         28         15          0
 
验证通过
 
 
再来看一下如果file#超过1023后oracle会怎么处理
 
SQL 10G>select file#,ts#,rfile# from v$datafile  where file#>1023;
     FILE#        TS#     RFILE# ---------- ---------- ----------       1024         14          1       1025         14          3       1026         14          4       1027         14          5       1028         14          6       1029         14          7       1030         14          8       1031         14          9       1032         14         10       1033         14         11       1034         14         12
     FILE#        TS#     RFILE# ---------- ---------- ----------       1035         14         13       1036         14         14       1037         15         14
可以看到在一个tablespace里面rfile#从1开始到1023
 
 
SQL 10G>select file#,rfile# from v$datafile  where ts#=14 order by file#;
     FILE#     RFILE# ---------- ----------          2          2         15         15         16         16         17         17         18         18         19         19         20         20         21         21         22         22         23         23         24         24        。。。。。。
    FILE#     RFILE# ---------- ----------       1015       1015       1016       1016       1017       1017       1018       1018       1019       1019       1020       1020       1021       1021       1022       1022       1023       1023       1024          1       1025          3
     FILE#     RFILE# ---------- ----------       1026          4       1027          5       1028          6       1029          7       1030          8       1031          9       1032         10       1033         11       1034         12       1035         13       1036         14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值