oracle rowid 使用
ROWID是数据的详细地址,通过rowid,oracle可以快速的定位某行具体的数据的位置。
ROWID可以分为物理rowid和逻辑rowid两种。普通的堆表中的rowid是物理rowid,索引组织表(IOT)的rowid是逻辑rowid。oracle提供了一种urowid的数据类型,同时支持物理和逻辑rowid。本文主要关注物理rowid
物理rowid又分为扩展rowid(extended rowid)和限制rowid(restricted rowid)两种格式。限制rowid主要是oracle7以前的rowid格式,现在已经不再使用,保留该类型只是为了兼容性。所以本文的提到物理rowid一般是指扩展rowid格式。
本文主要内容:
1.Rowid的显示形式
2.如何从rowid计算得到obj#,rfile#,block#,row#
3.如何从obj#,rfile#,block#,row#计算得到rowid
4.Rowid的内部存储格式
5.Index中存储的rowid
1.Rowid的显示形式
我们从rowid伪列里select出来的rowid是基于base64编码,一共有18位,分为4部分:
OOOOOOFFFBBBBBBRRR
其中:
OOOOOO:
六位表示data object id,根据object id可以确定segment。关于data object id和object id的区别,请参考http://www.orawh.com/index.php/archives/62
FFF:
三位表示相对文件号。根据该相对文件号可以得到绝对文件号,从而确定datafile。关于相对文件号和绝对文件号,请参考http://blog.itpub.net/post/330/22749
BBBBBB:六位表示data
block number。这里的data block number是相对于datafile的编号,而不是相对于tablespace的编号。
RRR:三位表示row
number。
Oracle提供了dbm_rowid来进行rowid的一些转换计算。
SQL>
create table test(id int,name varchar2(30));
Table
created.
SQL>
insert into test values(1,'a');
1
row created.
SQL>
commit;
Commit
complete.
SQL>
select rowid from test;
ROWID
------------------
AAAGbEAAHAAAAB8AAA
SQL>
select dbms_rowid.rowid_object(rowid) obj#,
2
dbms_rowid.rowid_relative_fno(rowid) rfile#,
3
dbms_rowid.rowid_block_number(rowid) block#,
4
dbms_rowid.rowid_row_number(rowid) row#,
5
dbms_rowid.rowid_to_absolute_fno(rowid,'SYS','TEST') file#
6 from test;
OBJ#
RFILE# BLOCK# ROW# FILE#
----------- ------------ ------------- ----------
----------
26308 7 124 0 7
2.
如何从rowid计算得到obj#,rfile#,block#,row#
rowid是base64编码的,用A~Z
a~z 0~9 +
/共64个字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63可以将其看做一个64进制的数。
所以,
obj#=AAAGbE=6*64^2+27*64+4=26308
rfile#=AAH=7
block#=AAAAB8=64+60=124
row#=AAA=0
3.
如何从obj#,rfile#,block#,row#计算得到rowid
实际上就是将十进制数转化成64进制数,当然,从二进制转化的规则比较简单点。
将二进制数从右到左,6个bit一组,然后将这6个bit组转成10进制数,就是A~Z
a~z 0~9 + /这64个字符的位置(从0开始),替换成base64的字符即可。
obj#=26308=110
011011 000100=6 27 4=G b E,补足成6位base64编码,左边填0,也就是A,结果为AAAGbE
rfile#=7=111=7=H,补足成3位,得到AAH
block#=124=1
111100=1 60=B 8,补足成6位,得到AAAAB8
row#=0,3位AAA
合起来就是AAAGbEAAHAAAAB8AAA
4.
Rowid的内部存储格式
虽然我们从rowid伪列中select出来的rowid是以base64字符显示的,但在oracie内部存储的时候还是以原值的二进制表示的。一个扩展rowid采用10个byte来存储,共80bit,其中obj#32bit,rfile#10bit,block#22bit,row#16bit。所以相对文件号不能超过1023,也就是一个表空间的数据文件不能超过1023个(不存在文件号为0的文件),一个datafile只能有2^22=4M个block,,一个block中不能超过2^16=64K行数据。而一个数据库内不能有超过2^32=4G个object。
SQL>
select dump(rowid,16) from test;
DUMP(ROWID,16)
--------------------------------------------
Typ=69
Len=10: 0,0,66,c4,1,c0,0,7c,0,0
00000000
00000000 01100110 11000100 00000001 11000000 00000000 01111100 00000000
00000000
最右边16bit为row#=00000000
00000000=0
接下来22bit为block#=000000
00000000 01111100=124
接下来10bit为rfile#=00000001
11=7
接下来32bit为obj#=00000000
00000000 01100110 11000100=26308
5.
Index中存储的rowid
a.
普通B-tree索引
SQL>
create index ix_test on test(id);
Index
created.
SQL>
select file_id,block_id from dba_extents where segment_name='IX_TEST' and
owner=user;
FILE_ID
BLOCK_ID
---------- ----------
7 129
---由于是assm表空间,去掉3个block的头
SQL>
alter system dump datafile 1 block 132;
System
altered.
得到trace文件内容如下(省略无关内容):
row#0[8024]
flag: -----, lock: 0
col 0; len 2; (2): c1 02 ---索引键数据ID=1
col 1; len 6;
(6): 01 c0 00 7c 00 00 ---对应的rowid记录
----- end of leaf block dump
-----
End dump data blocks tsn: 7 file#: 7 minblk 132 maxblk 132
普通索引中保存的rowid是不包括obj#的,但是分区表的global
index是包括obj#的,这是因为分区表包括多个segment,每个segment可能在不同的datafile中,根据表的obj#就无法确定该索引键对应的rowid(rfile#确定不了)。
01
c0 00 7c 00 00 转化为二进制 000000001 11000000 00000000 01111100 00000000 00000000
右边8bit
row#=0
接下来22bit
block#=000000 00000000 01111100=124
接下来10bit
rfile#=000000001 11=7
b.唯一索引
SQL>
drop index ix_test;
Index
dropped.
SQL>
create unique index ix_test on test(id);
Index
created.
SQL>
select file_id,block_id from dba_extents where segment_name='IX_TEST' and
owner=user;
FILE_ID
BLOCK_ID
---------- ----------
7 129
SQL>
alter system dump datafile 1 block 132;
System
altered.
得到trace文件内容如下:
row#0[8025]
flag: -----, lock: 0, data:(6): 01 c0 00 7c 00 00 ---对应的rowid记录
col 0; len 2;
(2): c1 02 ---索引键数据ID=1
----- end of leaf block dump -----
End dump data
blocks tsn: 7 file#: 7 minblk 132 maxblk 132
得到rowid为
01 c0 00 7c 00 00,具体的转换计算和前面的一样,就不重复了。
Base64编码说明
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。
如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
Base64编码表
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 | |||
---|---|---|---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
oracle rowid 使用的更多相关文章
- oracle rowid 详解
oracle rowid详解 今天是2013-09-15,存储在数据库中的每一行数据都有一个地址,oracle使用rowid数据类型在存储地址.rowid有如下类别: 1)physical rowid ...
- KingbaseES CTID 与 Oracle ROWID
熟悉oracle的人都知道ROWID可用于快速的数据访问,KingbaseES 由于自身MVCC机制的原因,ctid 作为 oracle rowid 的替代方案不合适,但currtid 还是基本可以满 ...
- ORACLE rowid,file# 和 rfile#
rowid简介 rowid就是唯一标志记录物理位置的一个id,在oracle 8版本以前,rowid由file#+block#+row#组成,占用6个bytes的空间,10 bit 的 file# , ...
- Oracle rowid
本文讨论的是关于oracle从8i开始引进object的概念后的rowid,即扩展(extended)的rowid:1.rowid的介绍先对rowid有个感官认识:SQL> select ROW ...
- Oracle ROWID具体解释
1.ROWID定义 ROWID:数据库中行的全局唯一地址 对于数据中的每一行,rowid伪列返回行的地址.rowid值主要包括下面信息: 对象的数据对象编号 该行所在的数据文件里的数据块 该行中数据块 ...
- oracle rowid 研究
SQL> create table tab01(id integer,val varchar(4)); Table created. SQL> insert into tab01 valu ...
- ORACLE rowid切分大表
通过如下sql获取rowid切分范围 ) || dbms_rowid.rowid_create(, DOI, lo_fno, lo_block, ) ) || ) || dbms_rowid.rowi ...
- Oracle 11g 编译使用BBED
环境:RHEL 6.4 + Oracle 11.2.0.4 1. 拷贝缺失文件 2. 编译BBED 3. BBED使用测试 Reference 1. 拷贝缺失文件 11g中缺失几个相关文件,但我们实际 ...
- Oracle corrupt block(坏块) 详解
转自:http://blog.csdn.net/tianlesoftware/article/details/5024966 一. 坏块说明 1.1 相关链接 在看坏块之前,先看几个相关的链接,在后面 ...
随机推荐
- [C# 网络编程系列]专题五:TCP编程
转自:http://www.cnblogs.com/zhili/archive/2012/08/25/2656840.html 前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来 ...
- JS思维导图
- 英语之路 zt
各位为英语而郁闷的兄弟姐妹们: 自从考完GRE和TOEFL以后,心有所感,本想写点心得,但是因为太懒没写成.今日风雨如晦,心中又有所感,于是一舒笔墨,写下我学英语的方法.俺知道有很多兄弟姐妹们和曾经的 ...
- HIbernate java.lang.AbstractMethodError: com.microsoft.jdbc.base.BaseDatabaseMetaData.supportsGetGeneratedKeys()Z
[HIbernate]java.lang.AbstractMethodError: com.microsoft.jdbc.base.BaseDatabaseMetaData.supportsGetGe ...
- linux下建立无线wifi------简单实用!
一 安装必要软件安装hostapd : sudo apt-get install hostapd安装DHCP: sudo apt-get install dhcp3-server 二 配置 ...
- HDU-2975 Billboard
Billboard Time Limit : 20000/8000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Su ...
- 关于 Unity NavMesh 数据的导出和使用
上周的工作重点转移到服务器寻路上来,刚刚做完没几天,总结一下,当时团队讨论的结果是使用 Unity 原生的 NavMesh 系统,然后将数据导出到服务器使用.我最初的思路是将导出的网格加载到服务器后, ...
- hadoop的安装
1. 获取linux操作系统 可以申请云主机. 2. 安装JDK,配置环境变量 sudo apt-get install openjdk-7-jdk vim /etc/profile 在配置文件中配置 ...
- java使用batik转换svg文件
svg是一种矢量图片格式,用来保存高保真的图片.我们可以用编辑器打开svg,我们可以看到svg文件其实就是一个xml文件,这种文件浏览器也可以识别.因此要查看svg用现成的浏览器就可以了.值得庆幸的是 ...
- vojis1523 NOI2002 贪吃的九头龙
描述 传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落. 有一天, ...