ITPub博客

首页 > Linux操作系统 > Linux操作系统 > oracle rowid (转载)

oracle rowid (转载)

原创 Linux操作系统 作者:paulyibinyi 时间:2008-03-28 18:01:05 0 删除 编辑
出处:http://wzwanghai.spaces.live.com/

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
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7199859/viewspace-219118/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
oracle 10g ocm oracle 10g/11g/12c ocp aix 6.1 administrator,ogg expert,ITSS 技术交流群 201703254 微信公众号 paulyibin 探讨技术,开心工作 电话 13719354869 ,深入研究数据库和开始研究big data

注册时间:2007-12-11

  • 博文量
    902
  • 访问量
    6504931