oracle rowid (轉載)
出處:
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
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)
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
------------------------------ ------------------------------ ------------------------------
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
--------------- ---------- ---------- ----------
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
----------------------------------------------------------------------------
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
------------ -----------
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
------------ -----------
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
--------------- ---------- ---------- ----------
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
---------- ---------- ----------
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
---------- ---------- ----------
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
。。。。。。
---------- ----------
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
---------- ----------
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
---------- ----------
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【ROWID】Oracle rowid說明Oracle
- oracle rowidOracle
- oracle8的ROWID結構(轉)Oracle
- ORACLE ROWID (zt)Oracle
- oracle常用包之dbms_rowid oracle rowid含義分析Oracle
- oracle rowid詳解Oracle
- Oracle rowid 詳解Oracle
- Oracle ROWID-1Oracle
- Oracle ROWID-2Oracle
- oracle rowid 的含義Oracle
- Oracle中rowid的用法Oracle
- 【oracle中rowid的用法】Oracle
- 轉---DBMS_ROWID.ROWID_CREATE來解決壞塊
- 索引ROWID轉換函式索引函式
- 轉載oracle awrOracle
- Oracle 透過rowid秒優SQLOracleSQL
- Oracle 通過rowid秒優SQLOracleSQL
- oracle8的ROWID結構Oracle
- oracle中的Rowid和UrowidOracle
- 【TUNE_ORACLE】ROWID切片SQL參考OracleSQL
- oracle中rownum和rowid的區別Oracle
- oracle壞塊的rowid方式修復Oracle
- 轉載Oracle AWR速查Oracle
- 轉載--oracle DML鎖Oracle
- Oracle redo解析之-4、rowid的計算Oracle Redo
- oracle 表中的rowid是什麼意思Oracle
- 【oracle rowid與rownum的使用與區別 】Oracle
- Oracle資料庫開發——瞭解rowidOracle資料庫
- oracle實驗記錄 (dbms_rowid使用)Oracle
- Oracle文件轉載 部落格Oracle
- 【轉載】oracle更新語法Oracle
- [轉載] Oracle EBS 入門Oracle
- ORACLE鎖機制-轉載Oracle
- oracle 裸裝置(轉載)Oracle
- oracle 日期相減 轉載Oracle
- 轉載:Oracle RAC簡介Oracle
- ORACLE碎片整理一(轉載)Oracle
- ORACLE碎片整理二(轉載)Oracle