设为首页 收藏本站
查看: 796|回复: 0

[经验分享] Oracle中rowid的用法(全面)

[复制链接]

尚未签到

发表于 2018-9-7 10:40:11 | 显示全部楼层 |阅读模式
  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>  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>>
  System>  得到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>>
  System>  得到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编码表
码值字符码值字符码值字符码值字符0A16Q32g48w1B17R33h49x2C18S34i50y3D19T35j51z4E20U36k5205F21V37l5316G22W38m5427H23X39n5538I24Y40o5649J25Z41p57510K26a42q58611L27b43r59712M28c44s60813N29d45t61914O30e46u62+15P31f47v63/  原文链接:http://hi.baidu.com/wwynhm/item/1a376fbc6063b7d084dd79a7
  关于《关于base64编码的原理及实现》


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-565815-1-1.html 上篇帖子: Centos 6.5安装oracle 11g 下篇帖子: oracle数据库安装前的环境配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表