目录
一、关于ROWID的解释
1、概念
ROWID是ORACLE中的一个重要的概念。用于定位数据库中一条记录的一个相对唯一地址值。通常情况下,该值在该行数据插入到数据库表时即被确定且唯一。
ROWID它是一个伪列,它并不实际存在于表中。它是ORACLE在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列。
所以根据一行数据的ROWID能找到一行数据的物理地址信息。从而快速地定位到数据行。
数据库的大多数操作都是通过ROWID来完成的,而且使用ROWID来进行单记录定位速度是最快的。
2、ROWID和索引的关系
要理解索引,必须先搞清楚ROWID。
B-Tree索引的每个索引条目具有两个字段。
第一个字段表示索引的键值,对于单列索引来说是一个值;而对于多列索引来说则是多个值组合在一起的。
第二个字段表示键值所对应的记录行的ROWID。所以索引能加快查询速度!
索引值→ROWID->将ROWID换算成一行数据的物理地址->得到一行数据
3、索引中的rowid
二、ROWID的格式:
1、rowid的格式
第一部分6位表示:该行数据所在的数据对象的 data_object_id; 第二部分3位表示:该行数据所在的相对数据文件的id; 第三部分6位表示:该数据行所在的数据块的编号; 第四部分3位表示:该行数据的行的编号;
索引就是保存了rowid后三个部分的信息。
索引是物理存在的,而rowid是伪列。所以索引可以用来快速地定位到数据行。
2、举个例子
(1)创建表
create table test(id number,name varchar2(10));
(2)直接查看空表的rowid和对象ID
col name for a10; select rowid,dump(rowid,16)as dump ,a.* from test a where rownum<10; col object_name for a15; col object_type for a15; select OWNER,OBJECT_NAME,OBJECT_ID,DATA_OBJECT_ID,OBJECT_TYPE from dba_objects where owner='TEST' and object_name='TEST';
(3)插入数据
insert into test values(1,'LLL01'); insert into test values(2,'LLL02'); insert into test values(3,'LLL04'); insert into test values(4,'LLL04'); insert into test values(5,'LLL05'); commit;
(4)重新查看表test
col name for a10; select rowid,dump(rowid,16)as dump ,a.* from test a where rownum<10;
(5)查看此表所在的文件及块位置
col segment_name for a10; col segment_type for a15; select owner,segment_name,segment_type,FILE_ID,BLOCK_ID from dba_extents where segment_name='TEST';
select owner,segment_name,segment_type,header_block from dba_segments where owner='TEST'and segment_name='TEST';
3、ROWD的表示方法
Oracle的物理扩展ROWID有18位,每位采用64位编码,分别用A~Z、a~z、0~9、+、/共64个字符表示。
A~Z表示0到25;a~z表示26到51;0~9表示52到61;+表示62;/表示63;刚好64个字符。
4、获得ROWD与手动计算
(1)获取ROWID
select rowid,dump(rowid,16)as dump ,a.* from test a where rownum<10;
ROWID DUMP ID NAME ------------------ ---------------------------------------- ---------- ---------- AAAlasAAEAAAACbAAA Typ=69 Len=10: 0,2,56,ac,1,0,0,9b,0,0 1 LLL01 AAAlasAAEAAAACbAAB Typ=69 Len=10: 0,2,56,ac,1,0,0,9b,0,1 2 LLL02 AAAlasAAEAAAACbAAC Typ=69 Len=10: 0,2,56,ac,1,0,0,9b,0,2 3 LLL03 AAAlasAAEAAAACbAAD Typ=69 Len=10: 0,2,56,ac,1,0,0,9b,0,3 4 LLL04 AAAlasAAEAAAACbAAE Typ=69 Len=10: 0,2,56,ac,1,0,0,9b,0,4 5 LLL05
(2)第一部分6位表示:
该行数据所在的数据对象的 data_object_id;
AAAlas(根据64位编码表获取) -->0,0,0,37,26,44 -->select 0*64*64*64*64*64+0*64*64*64*64+0*64*64*64+37*64*64+26*64+44*1 from dual; -->153260 -->select to_char(153260,'XXXXXXX') as hex_value from dual; -->256AC
(3)第二部分3位表示:
该行数据所在的相对数据文件的id;
AAE(根据64位编码表获取) -->0,0,4 -->select 0*64*64+0*64+4*1 from dual; -->4 -->select to_char(4,'X') as hex_value from dual; -->4
(4)第三部分6位表示:
该数据行所在的数据块的编号;
AAAACb -->0,0,0,0,2,27 -->select 0+0+0+0+2*64+27*1 from dual; -->155 -->select to_char(155,'XXX') as hex_value from dual; -->9B
(5)第四部分3位表示:
该行数据的行的编号;
AAA -->0,0,0 -->select 0+0+0 from dual; -->0
最终定位到对象object的id是153260,文件号是4,块是155,行位置是第0位,也就是第一行。
5、查询sql(获取文件对象,文件号及块位置)
SELECT ROWID, DBMS_ROWID.ROWID_OBJECT(ROWID) AS OBJECT, DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) AS FILENUM, DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) AS BLOCK, DBMS_ROWID.ROWID_ROW_NUMBER(ROWID) AS ROWN FROM test where rownum<10;
显然这个结果和我们手动计算的结果是一致的。