Oracle的數據字典表dba_objects包含了兩個字段,object_id, data_object_id,官方文檔上的解釋是:
object_id: Dictionary object number of the object. Data_object_id: Dictionary object number of the segment that contains the object.
直譯一下是:
object_id:對象的數據字典標示。 Data_object_id:包含對象的段的數據字典標示。
直譯下來還是很難理解,不過下面就詳細講解他們的區別:
首先,區別一下段(segment)和數據字典對象(dictionary object)的概念,段(segment)是指實實在在的分配了一個或者多個區(extents)來存儲數據。而數據字典對象(dictionary object)有可能有存儲區域,也有可能沒有。比如sequence,package,type這些對象並沒有存儲空間,所以並不存在段與之相關聯。所以這些對象的data_object_id都是空值。
XPCHILD/XPCHILD@ORCL>select object_id, data_object_id from dba_objects where object_name='SEQ_TEST'; OBJECT_ID DATA_OBJECT_ID ---------- -------------- 36385
下面看一個實際的例子,就能夠很好的理解這兩個概念了:
1. move 操作:
XPCHILD/XPCHILD@ORCL>select object_id, data_object_id from dba_objects where object_name='TEST1'; OBJECT_ID DATA_OBJECT_ID ---------- -------------- 36386 36386 1 row selected. XPCHILD/XPCHILD@ORCL>alter table test1 move; Table altered. XPCHILD/XPCHILD@ORCL>select object_id, data_object_id from dba_objects where object_name='TEST1'; OBJECT_ID DATA_OBJECT_ID ---------- -------------- 36386 36387
可以看到,test1在創建的時候,object_id, data_object_id都是36386.這是因為在創建的時候數據字典分配的機制是相同的。使用move操作,而本身move操作只是重新分配了空間來重組原來的數據,所以對象本身沒有發生變化,而是重新分配了段來存儲數據。
2. partition分區表
XPCHILD/XPCHILD@ORCL>CREATE TABLE test2 2 (id number, status char(1)) PARTITION BY list(status) (PARTITION p_t VALUES ('t'), PARTITION p_f VALUES ('f')); Table created. XPCHILD/XPCHILD@ORCL>select object_name, SUBOBJECT_NAME, OBJECT_ID, DATA_OBJECT_ID from dba_objects where object_name='TEST2'; OBJECT_NAM SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID ---------- ------------------------------ ---------- -------------- TEST2 P_F 36390 36390 TEST2 P_T 36389 36389 TEST2 36388 3 rows selected
這個地方可以看出,test2對象只有object_id,而真正只有分區才會有data_object_id, 因為每一個分區分配了一個段。
接着再創建一個普通表:
XPCHILD/XPCHILD@ORCL>CREATE TABLE test3 ( id number, status char(1) ); XPCHILD/XPCHILD@ORCL>select object_name, object_id, data_object_id from dba_objects where object_name='TEST3'; OBJECT_NAM OBJECT_ID DATA_OBJECT_ID ---------- ---------- -------------- TEST3 36391 36391
然后進行分區交換:
XPCHILD/XPCHILD@ORCL>alter table test2 exchange partition p_t with table test3 including indexes; Table altered.
最后再看一下相關的object_id和data_object_id:
XPCHILD/XPCHILD@ORCL>select object_name, SUBOBJECT_NAME, object_id, data_object_id from dba_objects where object_name in ('TEST2','TEST3'); OBJECT_NAM SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID ---------- ------------------------------ ---------- -------------- TEST2 P_F 36390 36390 TEST2 P_T 36389 36391 TEST2 36388 TEST3 36391 36389
所以這個地方顯而易見,在交換過后,對象的object_id都不會發生變變化,因為exchange操作並不會遷移數據,而僅僅是更改了對象的數據存儲即段得指向,也就是更改了對象的指針,這個指針指向的是數據存儲區域,即所謂的段。
3. 最后再看一下rowid
rowid是指數據塊中行的物理地址。看一下rowid的組成: XPCHILD/XPCHILD@ORCL>select rowid , 2 substr(rowid,1,6) "OBJECT", 3 substr(rowid,7,3) "FILE", 4 substr(rowid,10,6) "BLOCK", 5 substr(rowid,16,3) "ROW", 6 dbms_rowid.rowid_object(rowid) object_id, 7 id 8 from test3 t; ROWID OBJECT FILE BLOCK ROW OBJECT_ID ID ------------------ ------------ ------ ------------ ------ ---------- ---------- AAAI4lAAMAAAhssAAA AAAI4l AAM AAAhss AAA 36389 1 1 row selected. XPCHILD/XPCHILD@ORCL>alter table test3 move; Table altered. XPCHILD/XPCHILD@ORCL>select rowid , 2 substr(rowid,1,6) "OBJECT", 3 substr(rowid,7,3) "FILE", 4 substr(rowid,10,6) "BLOCK", 5 substr(rowid,16,3) "ROW", 6 dbms_rowid.rowid_object(rowid) object_id, 7 id 8 from test3 t; ROWID OBJECT FILE BLOCK ROW OBJECT_ID ID ------------------ ------------ ------ ------------ ------ ---------- ---------- AAAI4oAAMAAAhtMAAA AAAI4o AAM AAAhtM AAA 36392 1 1 row selected.
可以看到,rowid表示的是數據的在塊中的地址,所以在rowid的組成中,object_id是所謂的段的數據字典id,即data_object_id,如上所示,對表進行move操作,object_id發生了變化,即驗證了這個猜想。
