zoukankan      html  css  js  c++  java
  • [20190910]索引分支块中TERM使用什么字符表示.txt

    [20190910]索引分支块中TERM使用什么字符表示.txt

    --//做索引块转储,一些root,分支节点出现TERM,从来没有关注使用字符表示,简单探究看看。

    1.环境:
    SCOTT@test01p> @ ver1

    PORT_STRING                    VERSION        BANNER                                                                               CON_ID
    ------------------------------ -------------- -------------------------------------------------------------------------------- ----------
    IBMPC/WIN_NT64-9.1.0           12.2.0.1.0     Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production              0

    SCOTT@test01p> create table t as select to_char(rownum,'FM'||lpad('0',20,'0')) v1 from dual connect by level<=2000;
    Table created.

    SCOTT@test01p> create index i_t_v1 on t(v1);
    Index created.

    SCOTT@test01p> select header_file,header_block from dba_segments where owner=user and segment_name='I_T_V1';
    HEADER_FILE HEADER_BLOCK
    ----------- ------------
             11          506

    SCOTT@test01p> @ treedump i_t_v1
    old   1: select object_id from user_objects where object_name = upper('&&1') and object_type = 'INDEX'
    new   1: select object_id from user_objects where object_name = upper('i_t_v1') and object_type = 'INDEX'
     OBJECT_ID
    ----------
         27931

    old   1: alter session set events 'immediate trace name treedump level &m_index_id'
    new   1: alter session set events 'immediate trace name treedump level      27931'
    Session altered.        

    2.检查转储:
    --//转储内容:
    ----- begin tree dump
    branch: 0x2c001fb 46137851 (0: nrow: 9, level: 1)

    *** 2019-09-10T20:55:45.660043+08:00 (TEST01P(3))
       leaf: 0x2c001fc 46137852 (-1: row:224.224 avs:832)
       leaf: 0x2c001fd 46137853 (0: row:224.224 avs:832)
       leaf: 0x2c001fe 46137854 (1: row:224.224 avs:832)
       leaf: 0x2c001ff 46137855 (2: row:224.224 avs:832)
       leaf: 0x2c003e0 46138336 (3: row:224.224 avs:832)
       leaf: 0x2c003e1 46138337 (4: row:224.224 avs:832)
       leaf: 0x2c003e2 46138338 (5: row:224.224 avs:832)
       leaf: 0x2c003e3 46138339 (6: row:224.224 avs:832)
       leaf: 0x2c003e4 46138340 (7: row:208.208 avs:1344)
    ----- end tree dump

    --//0x2c001fb  = set dba 11,507 = alter system dump datafile 11 block 507
    --//转储root节点.

    SCOTT@test01p> alter system checkpoint ;
    System altered.

    SCOTT@test01p> alter system dump datafile 11 block 507;
    System altered.

    --//转储内容:
    Block header dump:  0x02c001fb
     Object id on Block? Y
     seg/obj: 0x6d1b  csc:  0x0000000000a2b4d9  itc: 1  flg: E  typ: 2 - INDEX
         brn: 0  bdba: 0x2c001f8 ver: 0x01 opc: 0
         inc: 0  exflg: 0
     
     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn  0x0000000000a2b4d9
    Branch block dump
    =================
    header address 629538892=0x2586004c
    kdxcolev 1
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 2
    kdxcosdc 0
    kdxconro 8
    kdxcofbo 44=0x2c
    kdxcofeo 7852=0x1eac
    kdxcoavs 7808
    kdxbrlmc 46137852=0x2c001fc
    kdxbrsno 0
    kdxbrbksz 8060
    kdxbr2urrc 0
    row#0[8034] dba: 46137853=0x2c001fd
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 32 35
    --//30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 32 35 = 00000000000000000225
    col 1; TERM
    --//出现TERM.
    row#1[8008] dba: 46137854=0x2c001fe
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 34 34 39
    col 1; TERM
    row#2[7982] dba: 46137855=0x2c001ff
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 36 37 33
    col 1; TERM
    row#3[7956] dba: 46138336=0x2c003e0
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 38 39 37
    col 1; TERM
    row#4[7930] dba: 46138337=0x2c003e1
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 31 32 31
    col 1; TERM
    row#5[7904] dba: 46138338=0x2c003e2
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 33 34 35
    col 1; TERM
    row#6[7878] dba: 46138339=0x2c003e3
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 35 36 39
    col 1; TERM
    row#7[7852] dba: 46138340=0x2c003e4
    col 0; len 20; (20):  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 37 39 33
    col 1; TERM
    ----- end of branch block dump -----
    End dump data blocks tsn: 4 file#: 11 minblk 507 maxblk 507

    --//转储可以发现TERM,表示终结,也就是叶子节点并不需要保存完整键值,仅仅部分就ok了。
    --//当然这里看不出来TERM的对应编码.看转储文件前面的内容如下:

    Dump of memory from 0x0000000025860000 to 0x0000000025862000
    025860000 0000A206 02C001FB 00A2B4DD 04010000  [................]
    025860010 0000AFCD 00000002 00006D1B 00A2B4D9  [.........m......]
    025860020 00008000 00320001 02C001F8 0000FFFF  [......2.........]
    025860030 00000000 00000000 00000000 80008000  [................]
    025860040 00A2B4D9 00000000 00000000 02800001  [................]
    025860050 00000000 002C0008 1E801EAC 02C001FC  [......,.........]
    025860060 00000000 00001F7C 1F481F62 1F141F2E  [....|...b.H.....]
    025860070 1EE01EFA 1EAC1EC6 00000000 00000000  [................]
    025860080 00000000 00000000 00000000 00000000  [................]
            Repeat 486 times
    025861EF0 00000000 00000000 02C003E4 30303014  [.............000]
    025861F00 30303030 30303030 30303030 39373130  [0000000000000179]
    025861F10 03E3FE33 301402C0 30303030 30303030  [3......000000000]
    025861F20 30303030 31303030 FE393635 02C003E2  [00000001569.....]
    025861F30 30303014 30303030 30303030 30303030  [.000000000000000]
    025861F40 34333130 03E1FE35 301402C0 30303030  [01345......00000]
    025861F50 30303030 30303030 31303030 FE313231  [000000000001121.]
    025861F60 02C003E0 30303014 30303030 30303030  [.....00000000000]
    025861F70 30303030 39383030 01FFFE37 301402C0  [000000897......0]
    025861F80 30303030 30303030 30303030 30303030  [0000000000000000]
    025861F90 FE333736 02C001FE 30303014 30303030  [673......0000000]
    025861FA0 30303030 30303030 34343030 01FDFE39  [0000000000449...]
    025861FB0 301402C0 30303030 30303030 30303030  [...0000000000000]
    025861FC0 30303030 FE353232 00000000 00000000  [0000225.........]
                       ~~~~~~~~
    025861FD0 00000000 00000000 00000000 00000000  [................]
            Repeat 1 times
    025861FF0 00000000 00000000 00000000 B4DD0601  [................]

    --//注意看下划线内容可以知道term对应编码是0xfe.
    --//当然我的例子特殊,如果上面的索引建立唯一索引就不会出现这样的情况,因为这样rowid在索引键值的前面。

    3.bbed观察看看:
    BBED> set dba 11,508
            DBA             0x02c001fc (46137852 11,508)
    --//注:windows下的bbed块出现偏移要+1.

    BBED> p kd_off
    b2 kd_off[0]    @100      8060
    b2 kd_off[1]    @102      0
    b2 kd_off[2]    @104      8034
    b2 kd_off[3]    @106      8008
    b2 kd_off[4]    @108      7982
    b2 kd_off[5]    @110      7956
    b2 kd_off[6]    @112      7930
    b2 kd_off[7]    @114      7904
    --//bbed看索引结构有一些问题,kd_off[0],kd_off[1]指向的偏移不对.实际上从kd_off[2]开始.

    BBED> x /rcx *kd_off[2]
    rowdata[186]                                @8110
    ------------
    child dba:     0x02c001fd
    separator key:
    col   0[20] @8115: 00000000000000000225
    col    1[0] @8136: *TERM*

    BBED> x /rcx *kd_off[3]
    rowdata[160]                                @8084
    ------------
    child dba:     0x02c001fe
    separator key:
    col   0[20] @8089: 00000000000000000449
    col    1[0] @8110: *TERM*
    ---//这里的偏移有问题.偏移8110是下一条记录的开始,估计是bbed的bug.

    BBED> dump /v offset 8110
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 508                               Offsets: 8110 to 8191                            Dba:0x02c001fc
    -----------------------------------------------------------------------------------------------------------
     fd01c002 14303030 30303030 30303030 30303030 30303232 35fe0000 00000000 l ??.00000000000000000225?.....
     00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 l ................................
     00000000 00000000 00000000 00000106 ddb4                                l ................荽
     <32 bytes per line>

    BBED> x /rcx offset 8110
    rowdata[186]                                @8110
    ------------
    child dba:     0x02c001fd
    separator key:
    col   0[20] @8115: 00000000000000000225
    col    1[0] @8136: *TERM*

    BBED> dump /v offset 8109 count 2
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 508                               Offsets: 8109 to 8110                            Dba:0x02c001fc
    -----------------------------------------------------------------------------------------------------------
     fefd                                                                    l �
     <32 bytes per line>

    --//bbed显示的x命令显示col 1的偏移有问题,实际上列长度是0.偏移8110是另一条记录.
    --//可以发现TERM实际上对应ASCII码是0xfe。这样就很好解析我以前遇到的问题。链接:
    --//http://blog.itpub.net/267265/viewspace-1291526/=>[20141008]索引字符串的长度问题.txt

    --//对于索引字符串的长度:
    --//1.当字符串长度小于等于127时,使用1个字节表示长度.
    --//2.当字符串大于等于128时,使用2个字节来保存长度,内容为字符串长度+0x8000.
    --//3.真搞不懂为什么与数据块的保存方式不同,oracle要创造2种不同的方式保存字符串.

    --//当时很不理解为什么oracle要创造2种不同的方式保存字符串,现在明白了。

    --//曾经写过一篇"varchar2(4000)如何保存",链接如下:
    --//http://blog.itpub.net/267265/viewspace-2148818/ => [20171218]varchar2(4000)如何保存.txt

    --//如果一行能被存储于一个数据块(data block)中,那么其行头(row header)所需容量将不少于 3 字节(byte)。在行头信息之后依次储存
    --//的是各列的列长(column length)及列值(column value)。列长存储于列值之前,如列值不超过250 字节,那么 Oracle使用1字节存储其
    --//列长;如列值超过 250 字节,则使用 3 字节存储其列长。列数据(column data)所需的存储空间取决于此列的数据类型(datatype)。如
    --//果某列的数据类型为变长(variable length)的,那么存储此列值所需的空间可能会随着数据更新而增长或缩小。

    --//当时的总结:
    --//1.如果列值长度小于等于250字节,Oracle使用1字节存储其列长.内容为字段的长度.
    --//2.如果列值长度超过250字节,则使用3字节存储其列长。前面1个字节使用0xfe(表示超过250),后面2个字节表示列值长度.

    --//很明显0xfe在数据块中的字符串长度指示器一部分,用来表示保存字符超过250字节。而索引TERM使用0xfe表示。
    --//这样索引字段字符串长度如果大于250,就不能再使用数据块中类似的方式保存键值长度。这样oraclea必须采用新的模式定义索引中字符串长度.
    --//语言不好表达,还是通过例子说明:

    4.继续测试:
    create table t1 (v1 varchar2(4000));
    insert into t1 values (lpad('1',127,'1'));
    insert into t1 values (lpad('2',128,'2'));
    insert into t1 values (lpad('3',4000,'3'));
    commit ;
    create index i_t1_v1 on t1(v1);
    alter system checkpoint ;

    SCOTT@test01p> select header_file,header_block from dba_segments where owner=user and segment_name='I_T1_V1';
    HEADER_FILE HEADER_BLOCK
    ----------- ------------
             11          410

    --//索引根节点在11,411.通过bbed观察:

    BBED> set dba 11,412
            DBA             0x02c0019c (46137756 11,412)

    BBED> p kd_off
    b2 kd_off[0]  @132      8036
    b2 kd_off[1]  @134      0
    b2 kd_off[2]  @136      7899

    BBED> x /rcx *kd_off[2]
    rowdata[4154]                               @7999
    -------------
    flag@7999:     0x00 (NONE)
    lock@8000:     0x00
    data key:
    col  0[127] @8002: 11111111...1111111111
    col    1[6] @8130:  0x02  0xc0  0x01  0x95  0x00  0x00

    BBED> dump /v offset 8001 count 10
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 412                               Offsets: 8001 to 8010                            Dba:0x02c0019c
    -----------------------------------------------------------------------------------------------------------
     7f313131 31313131 3131                                                  l .111111111
    <32 bytes per line>

    --//7f = 127 ,使用1个字节表示字符串长度.

    BBED> dump /v offset 138 count 4
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 412                               Offsets:  138 to  141                            Dba:0x02c0019c
    -----------------------------------------------------------------------------------------------------------
     501ea50e                                                                l P.?
    <32 bytes per line>

    --//字节颠倒顺序 0x1e50 = 7760, 0x0ea5 = 3749 .相对偏移在7760,3749,看前面kd_off[2]偏移可以看出绝对偏移要加100.

    BBED> x /rcx offset 7860
    rowdata[4015]                               @7860
    -------------
    flag@7860:     0x00 (NONE)
    lock@7861:     0x00
    data key:
    col  0[128] @7864: 22222...22222
    col    1[6] @7993:  0x02  0xc0  0x01  0x95  0x00  0x01

    BBED> dump /v offset 7862 count 10
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 412                               Offsets: 7862 to 7871                            Dba:0x02c0019c
    -----------------------------------------------------------------------------------------------------------
     80803232 32323232 3232                                                  l ..22222222
    <32 bytes per line>
    --//出现2次0x80.

    BBED> x /rcx offset 3849
    rowdata[4]                                  @3849
    ----------
    flag@3849:     0x00 (NONE)
    lock@3850:     0x00
    data key:
    col 0[4000] @3853: 3333............
    ........3333333
    col    1[6] @7854:  0x02  0xc0  0x01  0x95  0x00  0x02

    BBED> dump /v offset 3851 count 10
     File: D:APPORACLEORADATATESTTEST01PUSERS01.DBF (11)
     Block: 412                               Offsets: 3851 to 3860                            Dba:0x02c0019c
    -----------------------------------------------------------------------------------------------------------
     8fa03333 33333333 3333                                                  l .?3333333
     <32 bytes per line>

    --//0x8fa0 -0x8000 = 0xfa0 = 4000.

    --//对于索引字符串的长度:
    --//1.当字符串长度小于等于127时,使用1个字节表示长度.
    --//2.当字符串大于等于128时,使用2个字节来保存长度,内容为字符串长度+0x8000.

    --//以前学习oracle很不理解为什么数据块中字串长度小于等于250字节,Oracle使用1字节存储其列长.内容为字段的长度.
    --//为什么把边界定义在250. 0xff用来保存空值,0xfe作为>250字串长度指示器编码一部分(在索引表示TERM).
    --//按照这样的道理,oracle还预留了0xfb,0xfc,0xfd,不知道在那里会用上....

  • 相关阅读:
    svn环境搭建
    Svn正确的使用方法
    基于phpExcel写的excel类
    关于ecshop中jquery与js冲突解决的方案
    学习Javascript闭包(Closure)
    JS全局变量VAR和THIS
    python六十六课——单元测试(二)
    python六十五课——单元测试(一)
    python六十四课——高阶函数练习题(三)
    python六十四课——高阶函数练习题(二)
  • 原文地址:https://www.cnblogs.com/lfree/p/11503366.html
Copyright © 2011-2022 走看看