`
wsql
  • 浏览: 11771804 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

ORACLE ROWID的一点知识

 
阅读更多

oracle8的ROWID结构
2004-04-23 15:18 pm

来自:Linux文档
地址:http://linux.sheup.com/linux/linux3983.htm

1、为什么使用ROWID
ORACLE把ROWID作为B-树和其内部算法标示ROW的唯一标示。
在ORACLE8以前的版本中,ROWID标示FILE、BLOCK、ROW NUMBER,只用一个数字代
表FILE号。
在ORACLE8中,一个DATAFILE有两个数字代表:
一个绝对值,是整个数据库唯一的。可以看DBA_DATA_FILES中的FILE_ID。
一个相对值,在TABLESPACE中是唯一的,可以看DBA_DATA_FILES中的RELATIVE_
FNO。

新的ROWID使用相对值,所以必须存放SEGMENT的标示,否则就会混淆。所以ORAC
LE8在ROWID中加入对象的SEGMENT号,用来标示TABLE或者PARTITION。

2、ROWID的结构
使用base-64代码,包括a-z,A-Z,0-9,+,-。一共18位。
1-6位:代表OBJECT
7-9位:文件相对值
10-15:文件中的BLOCK
16-18:BLOCK中的SLOT值

3、TABLESPACE-Relative寻址方式
使用的是TABLESPACE-Relative寻址方式,多个文件可以有相同的相对值,因为它
们属于不同的TABLESPACE,所以不能从新的ROWID得到绝对地址,但是这没有问题
,因为当要处理某个OBJECT时,已经能确定它属于哪个TABLESAPCE了。在TABLES
PACE中,文件相对值是唯一的,所以ROWID还是可以唯一标示一个OBJECT。TABLE
SPACE-Relative寻址方式是ORACLE8中支持超大数据库的关键技术。

4、DATA OBJECT NUMBER
DATA OBJECT NUMBER用于指示SEGMENT,所有SEGMENT都有DATA OBJECT NUMBER,
存放在每个DATA BLOCK中,而且不重复。

最开始的时候,DBA_OBJECTS.OBJECT_ID=DBA_OBJECTS.DATA-OBJECT_ID,但是在
上述情况下DATA-OBJECT_ID会在如下情况下增加
TRUNCATE TABLE
MOVE PARTITION
ORACLE会检查ROWID中的DATA OBJECT NUMBER和BLOCK中的DATA OBJECT NUMBER,
保证他们之间的版本是一致的。
ORACLE也使用DATA OBJECT NUMBER以确保ROLLBACK的纪录和最新的SEGMENT纪录一
致。
要注意的是DATA OBJECT NUMBER不是OBJECT 的标志


5、RESTRICTED ROWID
ORACLE7的ROWID格式是
1-8位:BLOCK NUMBER
9-12位:ROW NUMBER
13-16位:FILE NUMBER
ORACLE8支持短的、旧格式的ROWID,作用是
对NOPARTITION TABLE的INDEX ENTRY
对PARTITION TABLE的LOCAL INDEX ENTRY
ROW Piece CHain pointer
受限ROWID的内部存放是6BYTE,
4BYTE=DATA BLOCK NUMBER
2BYTE=ROW NUMBER
这就是说,INDEX ENTRY使用6BYTE存放该ROWID,这对大多数INDEX足够了。但是
这种短ROWID不能使用在PATITION TABLE的GLOBAL INDEX上,因为PARTITION可能
跨TABLESPACE。显示这种ROWID依然是18位的

6、扩展的ROWID
ORACLE在内部存放时候是10 BYTE,包括(DATA OBJECT NUMBER,DATA BLOCK NU
MBER,ROW NUMBER)
ORACLE8使用扩展的ROWID:
PARTITION TABLE 的GLOBAL INDEX
SERVER 算法
扩展的ROWID在SELECT时,依然是18位的显示,存放在ROWID字段中。

7、在ORACLE8中使用ORACLE7的ROWID
从ORACLE8的DB中查询ORACLE7的ROWID时候,ROWID返回的是ORACLE7的格式,也可
以用在WHERE语句中。
从ORACLE7的DB中查询ORACLE8的ROWID时候,ROWID返回的是ORACLE8的格式,也可
以用在WHERE语句中,但是不能存放在ROWID字段中。但是你要用DBMS_ROWID 包来
解释之。
如果包含扩展的ORACLE8 ROWID,这不能把ORACLE8的数据IMPORT到ORACLE7中。从
ORACLE7中可以IMPORT到ORACLE8中。

8、APPLICATION的移植问题
一般程序的移植应该没有问题。只有在下面情况下才考虑移植问题:
application使用了rowid
table包括ROWID类型的字段
如果程序有如下情况,必须使用DBMS_ROWID包:
自己组合ROWID
自己分解ROWID
如果仅仅是传递ROWID到变量、或者仅仅做为一个整体使用,则可以不受影响。


9、数据的移植问题
无论使用EXPORT/IMPORT还使用移植工具,ORACLE7中的ROWID字段到了ORACLE8中
就自动扩展。
如果在某个字段内容中包含ROWID,则必须手工用DBMS_ROWID包来转换。

10、DBMS_ROWID包
由$ORACLE_HOME/rdbms/admin/dbmsutil.sql创建,其实在catproc.sql中包含着
。提供处理ROWID的一些函数。
ROWID_CREATE
ROWID_INFO
ROWID_TYPE
ROWID_OBJECT
ROWID_RELATIVE_FNO
ROWID_BLOCK_NUMBER
ROWID_TO_ABSOLUTE_FNO
ROWID_TO_EXTENDED
ROWID_TO_RESTRICTED
ROWID_VERIFY

DBMS_ROWID.ROWID_TO_EXTENDED
(old_rowid in ROWID,
schema_name in varchar2,
object_name in varchar2,
conversion_type in number
)
RETURN ROWID;
转换受限rowid到扩展rowid,用于转换旧的ROWID到ORACLE8的格式。


DBMS_ROWID.ROWID_TO_RESTRICTED
转换扩展的ROWID到受限的ROWID。

DBMS_ROWID.ROWID_VERIFY
判断一个受限的ROWID是否可以转换到扩展的格式


DBMS_ROWID.ROW_INFO
用于解释ROWID,可以得到DATA OBJECT NUMBER,RELATIVE FILE NUMBER,BLOCK
NUMBER和ROW NUMBER。

DBMS_ROWID.CREATE
生成ROWID。

结束


oracle ROWID结构分析

引自:http://rainnyzhong.bokee.com/5793871.html


Oracle的文档上没有介绍逻辑ROWID的编码规则,而且通过DUMP的结果也很难反推出编码规则。因此,本文只简单讨论一下逻辑ROWID的存储。

下面来看例子。


SQL> create table test_index (id number primary key, name varchar2(20)) organization index;

表已创建。

SQL> insert into test_index values (1, 'a');

已创建 1 行。

SQL> commit;

提交完成。

SQL> col dump_rowid format a60
SQL> select rowid, dump(rowid) dump_rowid from test_index;

ROWID DUMP_ROWID
--------------------------- ----------------------------------------
*BAFAB4wCwQL+ Typ=208 Len=10: 2,4,1,64,7,140,2,193,2,254

逻辑ROWID的DUMP结果前两位都是2和4,最后一位都是254,(我还没有发现其他的情况),由于逻辑ROWID和主键的值有关,所以长度是不定的,因此应该是用来表示开始和结束的。

第3、4位和物理ROWID一样,表示的是相对表空间的数据文件号乘以64的值。

第5、6位表示这条记录在数据文件的第几个BLOCK中。

从第7位开始到DUMP结果的倒数第二位,表示主键的值。首先是主键中第一个字段的长度,这里是2,然后是主键的值,由于是NUMBER类型,因此193,2表示数值1。如果是多个字段组成的主键,第一个字段之后是第二个字段的长度,然后是第二个字段的值……。

SQL> select (1*256 + 64)/64 from dual;

(1*256+64)/64
-------------
5

SQL> select 7*256 + 140 from dual;

7*256+140
----------
1932

SQL> alter system dump datafile 5 block 1932;

系统已更改。

找到相应的dump文件,可以发现刚才插入的记录。

Dump file f:oracleadmintest4udumptest4_ora_3828.trc
Thu Dec 23 00:17:53 2004
ORACLE V9.2.0.4.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.1 Service Pack 1, CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
Windows 2000 Version 5.1 Service Pack 1, CPU type 586
Instance name: test4

Redo thread mounted by this instance: 1

Oracle process number: 9

Windows thread id: 3828, image: ORACLE.EXE


*** 2004-12-23 00:17:53.361
*** SESSION ID:(8.82) 2004-12-23 00:17:53.301
Start dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932
buffer tsn: 5 rdba: 0x0140078c (5/1932)
scn: 0x0000.00e9f122 seq: 0x01 flg: 0x02 tail: 0xf1220601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x0140078c
Object id on Block? Y
seg/obj: 0x1e48 csc: 0x00.e9f113 itc: 2 flg: E typ: 2 - INDEX
brn: 0 bdba: 0x1400789 ver: 0x01
inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 0x0005.008.000000e7 0x00800226.005c.24 --U- 1 fsc 0x0000.00e9f122

Leaf block dump
===============
header address 71963236=0x44a1264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x90: opcode=0: iot flags=I-- is converted=Y
kdxconco 1
kdxcosdc 0
kdxconro 1
kdxcofbo 38=0x26
kdxcofeo 8026=0x1f5a
kdxcoavs 7988
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8026] flag: K----, lock: 2
col 0; len 2; (2): c1 02
tl: 5 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [ 1]
Dump of memory from 0x044A31C7 to 0x044A31C8
44A31C0 61010100 [...a]
----- end of leaf block dump -----
End dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932

可以看到,根据DUMP结果的3、4、5、6位可以定位记录的物理位置。

需要注意的是,索引组织表以主键的顺序存储数据,因此插入、更新和删除数据都可能造成一条记录的物理位置发生变化,这时通过ROWID 中的DATAFILE和BLOCK的信息可能就无法正确定位到记录的物理位置。当根据逻辑ROWID访问索引组织表时,首先会根据DATAFILE和 BLOCK信息去找到相应的BLOCK,检查数据是否在这个BLOCK中,如果不在,就通过逻辑ROWID中的主键信息去通过索引扫描,找到这条记录。这就是Oracle文档在提到的physical guess。

下面看一个由字符串和日期组成联合主键的例子。

SQL> create table test_index2 (id char(4), time date,
2 constraint pk_test_index2 primary key (id, time)) organization index;

表已创建。

SQL> insert into test_index2 values ('1', sysdate);

已创建 1 行。

SQL> col dump_rowid format a75
SQL> select rowid, dump(rowid) dump_rowid from test_index2;

ROWID DUMP_ROWID
---------------------------- ------------------------------------------------------------------
*BAFAB5QEMSAgIAd4aAwXASMT/g Typ=208 Len=20: 2,4,1,64,7,148,4,49,32,32,32,7,120,104,12,23,1,35,19,254

可以看出,第7位是字段id的长度4,然后是字符串1和三个空格的ASCII码,这是字符串的存储格式,后面跟着的7是字段time长度,后面七位是日期的存储格式。在逻辑ROWID中,数值、字符和日期类型的存储格式都和它们本身的存储格式一致,这里不在赘述。

一般情况下,使用一位来表示长度,但是如果长度超过了127(16进制DUMP的结果是7F),则长度开始用两位表示。第一位以8开头,这个8只是标识位,表明长度字段现在由两位来表示。例如长度128表示位8080,而支持的最大值3800表示为8ED8。

本文来自CSDN博客,转载请标明出处:file:///D:/my%20documents/oracle/ORACLE%20ROWID的一点知识%20-%20FALENT的专栏%20-%20CSDN博客.mht

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics