其实object_id和data_object_id同样是表示数据库对象的一个唯一标志,但是object_id表示的是逻辑id,data_object_id表示的是物理id。如果一些object没有物理属性的话那它就不存在data_object_id,例如procedure,function,package,data type,db link,mv定义,view定义,临时表,分区表定义等等这些object都是没有对应着某个segment,因此它们的data_object_id都为空。
当表刚创建的时候它的object_id和data_object_id都是相等的,但是如果表经过move或truncate后那么data_object_id将会有变化。
dba_objects已经有了object_id列来唯一标识一个对象,那么还要data_object_id列做什么?而在metalink上又没有找到dba_objects的解释。我执行如下查询:
SQL> select count(*) from dba_objects;
COUNT(*)
———-
29931
SQL> select count(*) from dba_objects where object_id <> data_object_id;
COUNT(*)
———-
121
发现在我的数据库中,又121个对象数据的object_id和data_object_id不一致。于是问人,曰在分区表的情况下,这两个字段不一致。可是我的数据库没有使用分区表。怎么回事呢?深究一下,得知:
表经过move/truncate之后,索引经过rebuild之后它们的object_id<>data_object_id
SQL> create table wwftest as select object_id, object_name, owner from all_objec
ts where rownum < 400;
表已创建。
SQL> create index ind_wwftest on wwftest(object_id);
索引已创建。
SQL> col object_name format a25
SQL> select object_name, object_id, data_object_id from dba_objects
2 where object_name like ‘%WWFTEST’;
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
———————— ———- ————–
IND_WWFTEST 33363 33363
WWFTEST 33362 33362
SQL> truncate table wwftest;
表已截掉。
SQL> select object_name, object_id, data_object_id from dba_objects
2 where object_name like ‘%WWFTEST’;
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
————————- ———- ————–
IND_WWFTEST 33363 33364
WWFTEST 33362 33365
SQL> alter table wwftest move;
表已更改。
SQL> select object_name, object_id, data_object_id from dba_objects
2 where object_name like ‘%WWFTEST’;
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
————————- ———- ————–
IND_WWFTEST 33363 33364
WWFTEST 33362 33366
SQL> alter index ind_wwftest rebuild;
索引已更改。
SQL> select object_name, object_id, data_object_id from dba_objects
2 where object_name like ‘%WWFTEST’;
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
————————- ———- ————–
IND_WWFTEST 33363 33367
WWFTEST 33362 33366
那么,data_object_id是用来做什么的呢?note 45888.1说的明白:
DATA_OBJECT_ID was introduced in 8.0 to track versions of the same segment (certain operations change the version). It is used to discover stale ROWIDs and stale undo records.
=======================================================
object_id和data_object_id的区别,delete和truncate的区别
手懒就转的一个小实验结果,证明了以下几个问题:
1.默认创建一个标识后,其object_id和data_object_id是一样的
2.当对表进行move/movecompress/truncate后,objecct_id不会变化但是data_object_id会变化
3.当使用move之后,其segment会改变,相应的data_object_id跟着变化,也就是把表换了一个段存储
4.当使用truncate后,其segment不变,但是data_object_id,也就是说其存储段未变,只是把该段中得区标志为未使用
5.由此对比delete,delete是把每个数据的数据块读出来,写上delete标记,另外还将delete的内容拷贝一份到undo,同时将动作写到redo文件。所以对比起来,truncate只是把原来的区标记为未使用,释放,然后给表段分配新的区。所以truncate比delete快很多,但是不能撤销。truncate属于ddl,delete属于dml。
object_id 是逻辑对象ID
data_object_id 是物理对象ID
SQL> create table test as select rownum rn fromdba_objects;
Table created.
SQL> select object_id,data_object_id fromdba_objects where object_name='TEST' AND WNER='SYS';
OBJECT_ID DATA_OBJECT_ID
6680 6680
SQL> select header_file,header_block,blocks fromdba_segments where segment_name
='TEST' and WNER='SYS';
HEADER_FILEHEADER_BLOCK BLOCKS
1 42921 16
SQL> alter table test move;
Table altered.
SQL> select object_id,data_object_id fromdba_objects where object_name='TEST' AND WNER='SYS';
OBJECT_ID DATA_OBJECT_ID
6680 6681
表经过move后,物理ID发生变化
SQL> select header_file,header_block,blocks fromdba_segments where segment_name='TEST' and WNER='SYS';
HEADER_FILEHEADER_BLOCK BLOCKS
1 43105 16
SQL> truncate table test;
Table truncated.
SQL> select header_file,header_block,blocks fromdba_segments where segment_name='TEST' and WNER='SYS';
HEADER_FILEHEADER_BLOCK BLOCKS
1 43105 8
SQL> select object_id,data_object_id fromdba_objects where object_name='TEST' AND WNER='SYS';
OBJECT_ID DATA_OBJECT_ID
6680 6682
表经过truncate 后 物理ID也发生变化
SQL> alter table test add(n number);
Table altered.
SQL> select object_id,data_object_id fromdba_objects where object_name='TEST' AND WNER='SYS';
OBJECT_ID DATA_OBJECT_ID
6680 6682
给表增加一个列,也没发生变化
所以总上所简述
只有当segment发生变化时data_object_id才发生变化
有时候我们根据rowid算时得到的data_object_id会误以为就是object_id,因为要是没有发生segment变化时
两者值是相等的