zoukankan      html  css  js  c++  java
  • orcal 中的orcal用法

    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
  • 相关阅读:
    121.买卖股票 求最大收益1 Best Time to Buy and Sell Stock
    409.求最长回文串的长度 LongestPalindrome
    202.快乐数 Happy Number
    459.(KMP)求字符串是否由模式重复构成 Repeated Substring Pattern
    326.是否为3的平方根 IsPowerOfThree
    231.是否为2的平方根 IsPowerOfTwo
    461.求两个数字转成二进制后的“汉明距离” Hamming Distance
    206.反转单链表 Reverse Linked List
    448. 数组中缺少的元素 Find All Numbers Disappeared in an Array
    常见表单元素处理
  • 原文地址:https://www.cnblogs.com/zhangzhiqin/p/9301010.html
Copyright © 2011-2022 走看看