ROWID是数据的详细地址,通过rowid,可以快速的定位某行具体的数据的位置。

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的区别,请参考

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的用法相关推荐

  1. oracle rowID切片,Oracle中的rowid

    ROWID是ORACLE中的一个重要的概念.用于定位数据库中一条记录的一个相对唯一地址值.通常情况下,该值在该行数据插入到数据库表时即被确定且唯一.ROWID它是一个伪列,它并不实际存在于表中.它是O ...

  2. oracle rowID切片,Oracle中ROWID详解

    Oracle的ROWID用来唯一标识表中的一条记录,是这条数据在数据库中存放的物理地址. Oracle的ROWID分为两种:物理ROWID和逻辑ROWID.索引组织表使用逻辑ROWID,其他类型的表使 ...

  3. su oracle eof,探讨shell中EOF的用法

    在shell脚本中,通常将EOF与 << 结合使用,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主Shell. EOF只是一个分界符,当然也可以用abcde替 ...

  4. oracle 函数 epoch,PostgreSQL中epoch的用法

    在PG数据库中,extract函数用于从一个日期中获取某个子集,比如获取年,月,日,时,分,秒等.例如: epoch这个字段也可以获取到相应的值,如图: 而epoch的含义官网上的原本解释如下: Fo ...

  5. Oracle中rowid的用法(全面)

    ROWID是数据的详细地址,通过rowid,Oracle可以快速的定位某行具体的数据的位置. ROWID可以分为物理rowid和逻辑rowid两种.普通的堆表中的rowid是物理rowid,索引组织表 ...

  6. oracle中rowid的用法

    rowid概述 rowid是一个用来唯一标记表中行的伪列.它是物理表中行数据的内部地址,包含两个地址,其一为指向数据表中包含该行的块所存放数据文件的地址,另一个是可以直接定位到数据行自身的这一行在数据 ...

  7. oracle rowid 优先级,Oracle中rowid的用法(全面)

    ROWID是数据的详细地址,通过rowid,Oracle可以快速的定位某行具体的数据的位置. ROWID可以分为物理rowid和逻辑rowid两种.普通的堆表中的rowid是物理rowid,索引组织表 ...

  8. oracle 切割 rowid,Oracle中rowid的用法(全面)

    ROWID是数据的详细地址,通过rowid,Oracle可以快速的定位某行具体的数据的位置. ROWID可以分为物理rowid和逻辑rowid两种.普通的堆表中的rowid是物理rowid,索引组织表 ...

  9. ORACLE 大表使用 rowid 切片备份到历史表

    ORACLE 大表使用 rowid 切片备份到历史表 概述与要求 思路 备份与清理表的信息 方案 操作前准备 切分字段 备份步骤 清理步骤 脚本 概述与要求 项目需求将几个5000万行大表先备份到历史 ...

最新文章

  1. Selenium2(WebDriver)总结(二)---Firefox的firebug插件参数设置(补充)
  2. 大白话系列之C#委托与事件讲解(一)
  3. 特征工程包含那些步骤?如何进行特征的迭代?
  4. 查sqlserver表结构说明的方法
  5. R1-012 Shell执行命令的顺序
  6. python123说句心里话的题_如何与回避型依恋的人谈恋爱?
  7. Ubuntu服务器安装lamp
  8. Spring MVC 基于注解的class文件打成jar包后注入失败
  9. LeetCode 685. 冗余连接 II(并查集)
  10. 显微镜下的大明内容_平凡故事展现炮火下人性光辉,李少红《解放·终局营救》创作全解...
  11. 清空session的方法
  12. 这几张图告诉你程序员的变化,最后一张图扎心了
  13. mbio期刊拒稿率_如何避免拒稿?
  14. Linux - ATT汇编基础
  15. CSS:淘宝商品展示样式
  16. 华为悦盒E6108无线投屏-机顶盒连接wifi-我的盒子-DLNA-手机视频有TV标识-点击TV标识
  17. python 实现大鱼吃小鱼小游戏(课程作业)
  18. 2019年Java大厂面试题讲解(周阳) 之Github学习(自学路上助推器)
  19. C++学生管理系统课程设计
  20. 短域名Andy.ge 安迪哥的启用

热门文章

  1. 超全计算机的基础知识,网工小白必看(下)
  2. Ansible 学习笔记(一)
  3. csdn服务器给我返回http 500, 呵呵哒!------后来才知道, 每天最多写5篇, 我晕啊, 能给个友好点的提示不?
  4. 多品种、小批量生产计划的编制方法与质量控制措施
  5. 一个微信 QQ 链接屏蔽检测监控工具,可加域名池,可 API 回调 及微信通知
  6. UBOOT启动流程中的BL0,BL1,BL2
  7. Flash 8打造的一个超酷的Flash Web站点
  8. 交换机、路由器、防火墙IOS导入、密码破解
  9. 关于IC卡密钥理解(中级篇)
  10. AngularJS 如何进行字符串换行 HTML 换行的互换