oracle rowid

来源:互联网 发布:12306抢票软件 编辑:程序博客网 时间:2024/05/01 07:28
搞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
http://blog.itpub.net/post/330/22749
 
继续上面的话题,我们猜想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                             TESTROWIDTEST                           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