zoukankan      html  css  js  c++  java
  • 【转】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^1664K行数据。而一个数据库内不能有超过2^32=4Gobject

    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

    /


    原文链接:http://hi.baidu.com/wwynhm/item/1a376fbc6063b7d084dd79a7

  • 相关阅读:
    Mac 删除并关闭.DS_Store
    python 使用AES加密16位
    python 使用AES加密时,提示模块不存在
    sql大全
    Mac 升级10.15后,安装软件时提示‘文件已损坏’的解决办法
    Django model Datefield和DateTimeField类型
    1013. 将数组分成和相等的三个部分
    python 批量pip安装包
    Ajax发送数据
    kafka实战教程(python操作kafka--理论篇)
  • 原文地址:https://www.cnblogs.com/autumnlj/p/5814852.html
Copyright © 2011-2022 走看看