oracle rowid (轉載)

paulyibinyi發表於2008-03-28
出處:

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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章