在解析Oracle rowid系列一里,我们简单探讨了Oracle rowid的格式及获取rowid的方法,在本篇中我们探讨的主题是:通过Oracle rowid真的可以唯一定位到表的一条记录吗?或者说在同一Oracle数据库中,rowid就一定唯一、没有重复的吗?
实验步骤:
1 构建cluster table并插入测试数据:
SQL> conn / as sysdba; Connected. SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production PL/SQL Release 11.2.0.1.0 - Production CORE 11.2.0.1.0 Production TNS for Linux: Version 11.2.0.1.0 - Production NLSRTL Version 11.2.0.1.0 - Production SQL> conn hr/hr; Connected. SQL> create cluster dept_emp_cluster(department_id number(4)); Cluster created. SQL> create index idx_dept_emp_cluster on cluster dept_emp_cluster; Index created. SQL> create table dept cluster dept_emp_cluster(department_id) 2 as select * from departments; Table created. SQL> create table emp cluster dept_emp_cluster(department_id) 2 as select * from employees; Table created. SQL> select count(*) from dept; COUNT(*) ---------- 27 SQL> select count(*) from emp; COUNT(*) ---------- 107
2 接下来我们分别查询emp、dept表中department_id=10的rowid:
SQL> select department_id,rowid from dept where department_id=10; DEPARTMENT_ID ROWID ------------- ------------------ 10 AAAUB3AAEAAAAK3AAA SQL> select department_id,rowid from emp where department_id=10; DEPARTMENT_ID ROWID ------------- ------------------ 10 AAAUB3AAEAAAAK3AAA SQL> select department_id,rowid, 2 dbms_rowid.rowid_object(rowid) object_id, 3 dbms_rowid.rowid_relative_fno(rowid) file_id, 4 dbms_rowid.rowid_block_number(rowid) block_id, 5 dbms_rowid.rowid_row_number(rowid) num 6 from dept where department_id=10; DEPARTMENT_ID ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ------------- ------------------ ---------- ---------- ---------- ---------- 10 AAAUB3AAEAAAAK3AAA 82039 4 695 0 SQL> select department_id,rowid, 2 dbms_rowid.rowid_object(rowid) object_id, 3 dbms_rowid.rowid_relative_fno(rowid) file_id, 4 dbms_rowid.rowid_block_number(rowid) block_id, 5 dbms_rowid.rowid_row_number(rowid) num 6 from emp where department_id=10; DEPARTMENT_ID ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ------------- ------------------ ---------- ---------- ---------- ---------- 10 AAAUB3AAEAAAAK3AAA 82039 4 695 0 SQL>
从上,我们看到对于dept、emp这两张不同的表,对于department_id=10的两条记录的rowid完全一样,均为AAAUB3AAEAAAAK3AAA。
其中AAAUB3为数据库对象号,即转成10进制后位82309;数据文件号为AAE=4,位于第4号数据文件上;位于第4号文件的第AAAAK3=695个数据块上。
为什么会这样呢?不是说,rowid是唯一的吗,通过rowid可以唯一定位表里的一条记录吗?可是,现在却有两张完全不同的表中的rowid竟然完全重复?
3 原来,我们这个场景比较特殊,对象号为82309的对象是一个聚簇表,而dept,emp是位于该cluster下的。那么,emp、dept表中拥有完全重复的rowid也就不足为奇了。因为,这本身就是聚簇表的特征。Oracle的Cluster Table就是要将不同表中的数据放在同一个数据块中存放。关于Cluster Table我们将在后续探讨。
SQL> select object_name,object_id,object_type 2 from user_objects where object_id='82039'; OBJECT_NAME OBJECT_ID OBJECT_TYPE -------------------- ---------- ------------------- DEPT_EMP_CLUSTER 82039 CLUSTER SQL> select table_name,tablespace_name,cluster_name from user_tables 2 where table_name in ('DEPT','EMP'); TABLE_NAME TABLESPACE_NAME CLUSTER_NAME ------------------------ ----------------------- -------------------- DEPT USERS DEPT_EMP_CLUSTER EMP USERS DEPT_EMP_CLUSTER SQL>
4 结论:对于普通的Heap Table,我们说rowid的确可以精确定位到表里的记录,并且任何两张表中得rowid绝对不会重复。而对于Cluster Table就不一样了,完全有可能会出现rowid重复的情况。