ITPUB??ì3
2010数据库技术大会
ITPUB论坛 » Oracle专题深入讨论 » bitmap 的一点探究


您有 2 条公共消息
  • 来自: 公共消息 标题: 3-5月ITPUB数据库 ... 内容: ITPUB与3月和5月分别安排了Oracle 11g DBA和Oracle性能优化培训,以及 ...
  • 来自: 公共消息 标题: ITPUB邮箱已经恢复 内容: ITPUB邮箱用户请注意,邮箱现在已经恢复 web访问地址 http://emai ...

    标题: [精华] bitmap 的一点探究
    离线 biti_rainy
    人生就是如此



    精华贴数 39
    个人空间 0
    技术积分 112720 (4)
    社区积分 12111 (165)
    注册日期 2001-12-12
    论坛徽章:55
    现任管理团队成员ITPUB元老年度论坛发贴之星年度论坛发贴之星ITPUB北京2009年会纪念徽章ITPUB北京九华山庄2008年会纪念徽章
    管理团队2007贡献徽章参与2007年甲骨文全球大会(中国上海)纪念ITPUB北京香山2007年会纪念徽章管理团队2006纪念徽章会员2007贡献徽章会员2006贡献徽章

    发表于 2003-4-19 16:15 
    bitmap 的一点探究

    1:bitmap 索引是分段存储的,也就是说很多条记录可能是分做了N段来存储,也就是有N个begin/end ,当新的记录 insert 而使用以前未曾使用过的物理地址的时候,会产生一个bitmap 段来存储,就算只有一条记录

    2: 当删除一条记录的时候,在bitmap 索引上做了一个delete 的标记并用一新的记录来标记了,下面请看具体的演示

    3: 当 dml发生的时候,会lock住某个值的存储bit的那一rowid所在的记录,参考下面的 row 中 lock ,这样显然会影响并发


    SQL> create table tn(a number, b number);

    Table created.

    SQL> insert into tn select rownum,mod(rownum,5) from all_objects where rownum < 21;

    20 rows created.

    SQL> commit;

    Commit complete.

    SQL> create bitmap index tn_bitmap on tn(b);

    Index created.

    SQL> exec show_space('tn_bitmap',user,'INDEX');
    Free Blocks.............................0
    Total Blocks............................16
    Total Bytes.............................131072
    Unused Blocks...........................14
    Unused Bytes............................114688
    Last Used Ext FileId....................3
    Last Used Ext BlockId...................1954
    Last Used Block.........................2

    PL/SQL procedure successfully completed.

    SQL> select * from tn;

             A          B
    ---------- ----------
             1          1
             2          2
             3          3
             4          4
             5          0
             6          1
             7          2
             8          3
             9          4
            10          0
            11          1

             A          B
    ---------- ----------
            12          2
            13          3
            14          4
            15          0
            16          1
            17          2
            18          3
            19          4
            20          0

    20 rows selected.

    SQL> alter system dump datafile 3 block 1955;

    System altered.

    Block header dump:  0x00c007a3
    Object id on Block? Y
    seg/obj: 0x66da  csc: 0x00.18a0d77  itc: 2  flg: -  typ: 2 - INDEX
         fsl: 0  fnx: 0x0 ver: 0x01

    Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   xid:  0x0000.000.00000000    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000
    0x02   xid:  0x0002.040.000000ea    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000

    Leaf block dump
    ===============
    header address 125987932=0x7826c5c
    kdxcolev 0
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 5
    kdxcofbo 46=0x2e
    kdxcofeo 7918=0x1eee
    kdxcoavs 7872
    kdxlespl 0
    kdxlende 0
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 8036
    row#0[8013] flag: -----, lock: 0
    col 0; len 1; (1):  80  ---表示值为0
    col 1; len 6; (6):  00 c0 7e 03 00 00  ---rowid 起点的block和行号
    col 2; len 6; (6):  00 c0 7e 03 00 17  ---rowid 结束的block和行号,注意17 = 16+7 = 23 ,也就是下面转换后的有效位置截止到23bit
    col 3; len 4; (4):  ca 10 42 08   ---把该值按照16进制数转化为 11001010 (首字节不表示rowid信息)   00010000 01000010 00001000 ,
    凡是从起点到结束点内的1表示该值存在,这里有 一个必须要注意的问题是,这样转化后的位置并不是真实的物理位置,在每个字节内部bit还要颠倒一下顺序,首字节不表示位置信息
    也就是说上面的应该转换为 00001000 01000010 00010000 ,发现正好每5个存在一个值为0的记录

    row#1[7990] flag: -----, lock: 0
    col 0; len 2; (2):  c1 02  ---表示值为1
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 0f  ---注意这里是f,也就是一共只有16位,因为1是第一条记录开始的,在16的位置就已经有5条了
    col 3; len 3; (3):  c9 21 84 注意这里的 21  84 正好16位,根据上面描述的规则转换后就是 10000100 00100001,4个1正好表示记录
    row#2[7966] flag: -----, lock: 0
    col 0; len 2; (2):  c1 03  ---表示值为2
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 42 08 01
    row#3[7942] flag: -----, lock: 0
    col 0; len 2; (2):  c1 04   ---表示值为3
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 84 10 02
    row#4[7918] flag: -----, lock: 0
    col 0; len 2; (2):  c1 05   ---表示值为4
    col 1; len 6; (6):  00 c0 7e 03 00 00  
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 08 21 04
    ----- end of leaf block dump -----
    End dump data blocks tsn: 2 file#: 3 minblk 1955 maxblk 1955



    SQL> delete from tn where a = 2;

    1 row deleted.

    SQL> commit;

    Commit complete.

    SQL> alter system dump datafile 3 block 1955;

    System altered.

    SQL>

    Block header dump:  0x00c007a3
    Object id on Block? Y
    seg/obj: 0x66da  csc: 0x00.18a0d77  itc: 2  flg: -  typ: 2 - INDEX
         fsl: 0  fnx: 0x0 ver: 0x01

    Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   xid:  0x0000.000.00000000    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000
    0x02   xid:  0x0003.047.000000e9    uba: 0x00800dba.00d9.1f  --U-    2  fsc 0x001a.018a0d7d

    Leaf block dump
    ===============
    header address 125987932=0x7826c5c
    kdxcolev 0
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 6
    kdxcofbo 48=0x30
    kdxcofeo 7894=0x1ed6
    kdxcoavs 7846
    kdxlespl 0
    kdxlende 1
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 8036
    row#0[8013] flag: -----, lock: 0
    col 0; len 1; (1):  80
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 10 42 08
    row#1[7990] flag: -----, lock: 0
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 0f
    col 3; len 3; (3):  c9 21 84
    row#2[7894] flag: -----, lock: 2  ---这是删除后的拷贝,我们发现删除的时候该行已经加锁  lock  : 2  
    col 0; len 2; (2):  c1 03
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 40 08 01  ---我们发现 ca 42  已经变成  ca  40 ,也就是已经少掉一位bit了,正好是删除的那一条记录
    row#3[7966] flag: ---D-, lock: 2  ---这里我们发现值为2的记录已经有删除过的 ---D- ,D表示delete
    col 0; len 2; (2):  c1 03
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 42 08 01
    row#4[7942] flag: -----, lock: 0
    col 0; len 2; (2):  c1 04
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 84 10 02
    row#5[7918] flag: -----, lock: 0
    col 0; len 2; (2):  c1 05
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 17
    col 3; len 4; (4):  ca 08 21 04
    ----- end of leaf block dump -----
    End dump data blocks tsn: 2 file#: 3 minblk 1955 maxblk 1955


    __________________
    只看该作者    顶部
    离线 biti_rainy
    人生就是如此



    精华贴数 39
    个人空间 0
    技术积分 112720 (4)
    社区积分 12111 (165)
    注册日期 2001-12-12
    论坛徽章:55
    现任管理团队成员ITPUB元老年度论坛发贴之星年度论坛发贴之星ITPUB北京2009年会纪念徽章ITPUB北京九华山庄2008年会纪念徽章
    管理团队2007贡献徽章参与2007年甲骨文全球大会(中国上海)纪念ITPUB北京香山2007年会纪念徽章管理团队2006纪念徽章会员2007贡献徽章会员2006贡献徽章

    发表于 2003-4-20 10:53 
    再继续补充

    首先truncate 表所有数据
    truncate table tn;

    SQL> exec show_space('tn_bitmap','i');
    Free Blocks.............................0
    Total Blocks............................16
    Total Bytes.............................131072
    Unused Blocks...........................14
    Unused Bytes............................114688
    Last Used Ext FileId....................3
    Last Used Ext BlockId...................1954
    Last Used Block.........................2

    PL/SQL procedure successfully completed.

    可以看出索引是空的

    然后插入一条数据

    SQL> insert into tn values(1,1);

    1 row created.

    SQL> commit;

    Commit complete.

    SQL> alter system dump datafile 3 block 1955;

    System altered.



    row#0[8009] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 1; (1):  00
    row#1[8030] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL




    SQL>  insert into tn values(1,1);

    1 row created.

    SQL> commit;

    Commit complete.

    SQL>  alter system dump datafile 3 block 1955;

    System altered.



    row#0[8009] flag: ---D-, lock: 2  -- 标记删除,下面一份是拷贝
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 1; (1):  00
    row#1[7987] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00 00---07 正好表示8  rows
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 03  -- 03 正好表示2条记录被插入



    SQL>  insert into tn values(1,1);

    1 row created.

    SQL>  alter system dump datafile 3 block 1955;

    System altered.

    row#0[7987] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 03
    row#1[7965] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 07  -- 07 正好表示3条记录被插入



    SQL>  insert into tn values(1,1);

    1 row created.

    SQL>  insert into tn values(1,1);

    1 row created.

    SQL>  insert into tn values(1,1);

    1 row created.

    SQL>  insert into tn values(1,1);

    1 row created.

    SQL>  insert into tn values(1,1);

    1 row created.

    SQL> commit;

    Commit complete.

    SQL>  alter system dump datafile 3 block 1955;

    System altered.

    我们在同一个session中同一个事务连续插入5条记录,发现在bitmap中居然做了5个拷贝

    row#0[7987] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 03
    row#1[7965] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 07
    row#2[7943] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 0f
    row#3[7921] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 1f
    row#4[7899] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 3f
    row#5[7877] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 7f
    row#6[7855] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 ff -- ff 正好表示8条记录被插入


    SQL>  insert into tn values(1,1);

    1 row created.

    SQL> commit;

    Commit complete.

    SQL>   alter system dump datafile 3 block 1955;

    System altered.

    SQL>

    -- 上一个bitmap段存储表示8条记录,我们再插入第9条记录再来看

    row#0[7855] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 00
    col 2; len 6; (6):  00 c0 7e 03 00 07
    col 3; len 2; (2):  c8 ff  -- 8条记录已满,也把前面的前8条的多拷贝给清除掉了
    row#1[7834] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  00 c0 7e 03 00 08
    col 2; len 6; (6):  00 c0 7e 03 00 0f
    col 3; len 1; (1):  00 新插入的第9条记录被新的从 08 --  0f  这8个字节用来存储


    综合上面的实验可以看出,当单条insert发生的时候,会以8条记录为一个bitmap row 来存储,这正好是一个字节的bit,并且就算是
    相同事务中的insert也会导致大量的拷贝和lock产生,严重影响性能,甚至可能发生行迁移等严重问题,所以在经常发生变化的表中
    我们不应该采用 bitmap index ,当发生update 的时候情形更为复杂,暂时不予讨论了



    __________________
    只看该作者    顶部
    离线 biti_rainy
    人生就是如此



    精华贴数 39
    个人空间 0
    技术积分 112720 (4)
    社区积分 12111 (165)
    注册日期 2001-12-12
    论坛徽章:55
    现任管理团队成员ITPUB元老年度论坛发贴之星年度论坛发贴之星ITPUB北京2009年会纪念徽章ITPUB北京九华山庄2008年会纪念徽章
    管理团队2007贡献徽章参与2007年甲骨文全球大会(中国上海)纪念ITPUB北京香山2007年会纪念徽章管理团队2006纪念徽章会员2007贡献徽章会员2006贡献徽章

    发表于 2003-4-23 16:59 
    转 yangtingkun 的帖子

    http://itpub.net/showthread.php?threadid=115221

    SQL> truncate table tn;

    表已截掉。

    SQL> exec show_space('tn_bitmap',user,'INDEX');
    Free Blocks.............................0
    Total Blocks............................3
    Total Bytes.............................12288
    Unused Blocks...........................1
    Unused Bytes............................4096
    Last Used Ext FileId....................1
    Last Used Ext BlockId...................26474
    Last Used Block.........................2

    PL/SQL 过程已成功完成。

    SQL> alter system dump datafile 1 block 26475;

    系统已更改。

    Leaf block dump
    ===============
    header address 83060828=0x4f3685c
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 0
    kdxcofbo 36=0x24
    kdxcofeo 3940=0xf64
    kdxcoavs 3904
    kdxlespl 0
    kdxlende 0
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 3940
    ----- end of leaf block dump -----
    End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475
    索引已经清空

    SQL> insert into tn values (1, 1);

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    SQL> /

    已创建 1 行。

    依次插入10行数据。

    SQL> commit;

    提交完成。

    SQL> alter system dump datafile 1 block 26475;

    系统已更改。

    Leaf block dump
    ===============
    header address 83060828=0x4f3685c
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 11
    kdxcofbo 58=0x3a
    kdxcofeo 3716=0xe84
    kdxcoavs 3658
    kdxlespl 0
    kdxlende 9
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 3940
    row#0[3913] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 1; (1): 00
    row#1[3891] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 03
    row#2[3869] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 07
    row#3[3847] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 0f
    row#4[3825] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 1f
    row#5[3803] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 3f
    row#6[3781] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 7f
    row#7[3759] flag: -----, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 07
    col 3; len 2; (2): c8 ff
    row#8[3738] flag: ---D-, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 08
    col 2; len 6; (6): 00 40 67 68 00 0f
    col 3; len 1; (1): 00
    row#9[3716] flag: -----, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 08
    col 2; len 6; (6): 00 40 67 68 00 0f
    col 3; len 2; (2): c8 03
    row#10[3934] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL
    ----- end of leaf block dump -----
    End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475

    oracle对每次插入的数据都进行索引。


    SQL> truncate table tn;

    表已截掉。

    SQL> alter system dump datafile 1 block 26475;

    系统已更改。

    Leaf block dump
    ===============
    header address 83060828=0x4f3685c
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 0
    kdxcofbo 36=0x24
    kdxcofeo 3940=0xf64
    kdxcoavs 3904
    kdxlespl 0
    kdxlende 0
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 3940
    ----- end of leaf block dump -----

    一次性插入10条数据
    SQL> insert into tn select 1,1 from user_objects where rownum < 11;

    已创建10行。

    SQL> commit;

    提交完成。

    SQL> alter system dump datafile 1 block 26475;

    系统已更改。

    Leaf block dump
    ===============
    header address 83060828=0x4f3685c
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 2
    kdxcofbo 40=0x28
    kdxcofeo 3911=0xf47
    kdxcoavs 3871
    kdxlespl 0
    kdxlende 1
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 3940
    row#0[3911] flag: -----, lock: 2
    col 0; len 2; (2): c1 02
    col 1; len 6; (6): 00 40 67 68 00 00
    col 2; len 6; (6): 00 40 67 68 00 0f
    col 3; len 3; (3): c9 ff 03 一次性插入的数据,oracle会对整批数据进行bitmap索引。
    row#1[3934] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL
    ----- end of leaf block dump -----
    End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475

    因此我认为对于包含bitmap索引的表应当减少对数据库操作的数量。运用批量入库的方法会使性能得到较大的提高。

    有什么不对的地方还请指正。


    my  reply:

    综合上面的实验可以看出,当单条insert发生的时候,会以8条记录为一个bitmap row 来存储,这正好是一个字节的bit,并且就算是
    相同事务中的insert也会导致大量的拷贝和lock产生,严重影响性能,甚至可能发生行迁移等严重问题,所以在经常发生变化的表中
    我们不应该采用 bitmap index ,当发生update 的时候情形更为复杂,暂时不予讨论了



    结合
    前面的第一条:
    :bitmap 索引是分段存储的,也就是说很多条记录可能是分做了N段来存储,也就是有N个begin/end ,当新的记录 insert 而使用以前未曾使用过的物理地址的时候,会产生一个bitmap 段来存储,就算只有一条记录


    所以我的实验中可能没有很好的做归纳,但是现象都是有的,描述的比较零散



    就是说假如你们每天入库 1000万条记录
    那创建 bitmap 索引的这个列有多少不同的值,如果有10万个不同的值以上,那采用 bitmap 是否合适就值得考虑了


    __________________
    只看该作者    顶部
    离线 grassbell
    曾经的深入讨论区斑竹:)


    精华贴数 9
    个人空间 0
    技术积分 11854 (128)
    社区积分 370 (2089)
    注册日期 2003-6-13
    论坛徽章:6
    管理团队成员ITPUB北京九华山庄2008年会纪念徽章参与2007年甲骨文全球大会(中国上海)纪念管理团队2006纪念徽章会员2006贡献徽章授权会员
          

    发表于 2004-7-5 16:03 
    本想写一写对bitmap的看法,搜了一下,看到biti早在我还没开始学习oracle的时候,就已经写过了!


    __________________
    不是自己的,多研究,多做实验,把心得写出来,变成自己的

    欢迎访问Alibaba DBA 团队Blog: www.alidba.net

    http://twitter.com/chndonny
    只看该作者    顶部
    离线 yangtingkun
    版主


    精华贴数 12
    个人空间 69126
    技术积分 49460 (15)
    社区积分 3213 (554)
    注册日期 2001-12-29
    论坛徽章:162
    现任管理团队成员BLOG每日发帖之星2010新春纪念徽章2010年世界杯参赛球队:意大利BLOG每日发帖之星BLOG每日发帖之星
    BLOG每日发帖之星BLOG每日发帖之星BLOG每日发帖之星2010新春纪念徽章  

    发表于 2004-7-6 10:11 
    前一段又仔细研究了一下bitmap索引。
    测试结果和biti的描述有些出入,下面把结果贴处理,大家讨论讨论


    SQL> create table test_bitmap (id number, name varchar2(20), age number(3));

    表已创建。

    SQL> create bitmap index ind_b_test_bitmap_age on test_bitmap (age);

    索引已创建。

    SQL> set serverout on
    SQL> exec p_unused_space('ind_b_test_bitmap_age', 'index')
    total_blocks is 64
    total_bytes is 1048576
    unused_blocks is 60
    unused_bytes is 983040
    last_used_extent_file_id is 11
    last_used_extent_block_id is 1348
    last_used_block is 4

    PL/SQL 过程已成功完成。

    SQL> insert into test_bitmap values (1, 'aaa', 1);

    已创建 1 行。

    SQL> alter system dump datafile 11 block 1352;

    系统已更改。



    Leaf block dump
    ===============
    header address 141643364=0x8714e64
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 2
    kdxcofbo 40=0x28
    kdxcofeo 16201=0x3f49
    kdxcoavs 16161
    kdxlespl 0
    kdxlende 1
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 16228
    row#0[16201] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 1; (1):  00 当一个段中,只有一条记录的时候,oracle不是采用bitmap映射的方式,而是直接给出这条记录在这个段中的位置。例如这里的00表示了这个段中的第一条记录
    row#1[16222] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL
    ----- end of leaf block dump -----
    End dump data blocks tsn: 11 file#: 11 minblk 1352 maxblk 1352


    __________________
    学习ORACLE最大的障碍是什么——浮躁

    http://yangtingkun.itpub.net

    个人BLOG文章索引:http://www.itpub.net/699527.html

    11g的一点研究:http://www.itpub.net/852861.html
    只看该作者    顶部
    离线 grassbell
    曾经的深入讨论区斑竹:)


    精华贴数 9
    个人空间 0
    技术积分 11854 (128)
    社区积分 370 (2089)
    注册日期 2003-6-13
    论坛徽章:6
    管理团队成员ITPUB北京九华山庄2008年会纪念徽章参与2007年甲骨文全球大会(中国上海)纪念管理团队2006纪念徽章会员2006贡献徽章授权会员
          

    发表于 2004-7-6 10:20 
    是的,我也发现这个问题。比如你再插入2,这个值就变成 01
    但是再插入2,就会使用bitmap了。

    还有一个问题就是,begin/end rowid 的范围是怎么定的?
    比如有的例子中是02 c0 05 16 00 00~~ 02 c0 05 16 00 17
    而有的是        00 c0 7e 03 00 00~~ 00 c0 7e 03 00 0f


    __________________
    不是自己的,多研究,多做实验,把心得写出来,变成自己的

    欢迎访问Alibaba DBA 团队Blog: www.alidba.net

    http://twitter.com/chndonny
    只看该作者    顶部
    离线 yangtingkun
    版主


    精华贴数 12
    个人空间 69126
    技术积分 49460 (15)
    社区积分 3213 (554)
    注册日期 2001-12-29
    论坛徽章:162
    现任管理团队成员BLOG每日发帖之星2010新春纪念徽章2010年世界杯参赛球队:意大利BLOG每日发帖之星BLOG每日发帖之星
    BLOG每日发帖之星BLOG每日发帖之星BLOG每日发帖之星2010新春纪念徽章  

    发表于 2004-7-6 10:22 
    SQL> insert into test_bitmap values (2, 'aaa', 1);

    已创建 1 行。

    SQL> insert into test_bitmap values (3, 'a', 2);

    已创建 1 行。

    SQL> select rowid, id, age from test_bitmap;

    ROWID                      ID        AGE
    ------------------ ---------- ----------
    AAAH2WAALAAAAUWAAA          1          1
    AAAH2WAALAAAAUWAAB          2          1
    AAAH2WAALAAAAUWAAC          3          2

    SQL> alter system dump datafile 11 block 1352;

    系统已更改。


    Leaf block dump
    ===============
    header address 141643364=0x8714e64
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 4
    kdxcofbo 44=0x2c
    kdxcofeo 16158=0x3f1e
    kdxcoavs 16114
    kdxlespl 0
    kdxlende 2
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 16228
    row#0[16201] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 1; (1):  00
    row#1[16179] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 2; (2):  c8 03  一旦这个索引段中存放的记录超过两条就采用了bit位置表示法
    row#2[16158] flag: -----, lock: 2
    col 0; len 2; (2):  c1 03
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 1; (1):  02  这个02表示的是第三条记录。不过这个还不好确定02表示的相对位置还是就是rowid的最后两位。

    row#3[16222] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL
    ----- end of leaf block dump -----
    End dump data blocks tsn: 11 file#: 11 minblk 1352 maxblk 1352


    __________________
    学习ORACLE最大的障碍是什么——浮躁

    http://yangtingkun.itpub.net

    个人BLOG文章索引:http://www.itpub.net/699527.html

    11g的一点研究:http://www.itpub.net/852861.html
    只看该作者    顶部
    离线 grassbell
    曾经的深入讨论区斑竹:)


    精华贴数 9
    个人空间 0
    技术积分 11854 (128)
    社区积分 370 (2089)
    注册日期 2003-6-13
    论坛徽章:6
    管理团队成员ITPUB北京九华山庄2008年会纪念徽章参与2007年甲骨文全球大会(中国上海)纪念管理团队2006纪念徽章会员2006贡献徽章授权会员
          

    发表于 2004-7-6 10:27 
    是相对位置:
    row#6[7817] flag: -----, lock: 2
    col 0; len 2; (2):  c1 08
    col 1; len 6; (6):  00 c0 02 f2 00 08
    col 2; len 6; (6):  00 c0 02 f2 00 0f
    col 3; len 1; (1):  01

    01应该表示 rowid=00 c0 02 f2 00 09


    __________________
    不是自己的,多研究,多做实验,把心得写出来,变成自己的

    欢迎访问Alibaba DBA 团队Blog: www.alidba.net

    http://twitter.com/chndonny
    只看该作者    顶部
    离线 yangtingkun
    版主


    精华贴数 12
    个人空间 69126
    技术积分 49460 (15)
    社区积分 3213 (554)
    注册日期 2001-12-29
    论坛徽章:162
    现任管理团队成员BLOG每日发帖之星2010新春纪念徽章2010年世界杯参赛球队:意大利BLOG每日发帖之星BLOG每日发帖之星
    BLOG每日发帖之星BLOG每日发帖之星BLOG每日发帖之星2010新春纪念徽章  

    发表于 2004-7-6 10:32 
    SQL> insert into test_bitmap select 3+rownum, 'a', 1 from user_tables where rownum < 7;

    已创建6行。

    SQL> insert into test_bitmap values (10, 'b', 3);

    已创建 1 行。

    SQL> select rowid, id, age from test_bitmap;

    ROWID                      ID        AGE
    ------------------ ---------- ----------
    AAAH2WAALAAAAUWAAA          1          1
    AAAH2WAALAAAAUWAAB          2          1
    AAAH2WAALAAAAUWAAC          3          2
    AAAH2WAALAAAAUWAAD          4          1
    AAAH2WAALAAAAUWAAE          5          1
    AAAH2WAALAAAAUWAAF          6          1
    AAAH2WAALAAAAUWAAG          7          1
    AAAH2WAALAAAAUWAAH          8          1
    AAAH2WAALAAAAUWAAI          9          1
    AAAH2WAALAAAAUWAAJ         10          3

    已选择10行。

    SQL> alter system dump datafile 11 block 1352;

    系统已更改。


    Leaf block dump
    ===============
    header address 141636196=0x8713264
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
    kdxconco 4
    kdxcosdc 0
    kdxconro 7
    kdxcofbo 50=0x32
    kdxcofeo 16094=0x3ede
    kdxcoavs 16044
    kdxlespl 0
    kdxlende 3
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 16228
    row#0[16201] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 1; (1):  00
    row#1[16179] flag: ---D-, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 2; (2):  c8 03
    row#2[16136] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 2; (2):  c8 fb
    row#3[16115] flag: -----, lock: 2
    col 0; len 2; (2):  c1 02
    col 1; len 6; (6):  02 c0 05 16 00 08
    col 2; len 6; (6):  02 c0 05 16 00 0f
    col 3; len 1; (1):  00
    row#4[16158] flag: -----, lock: 2
    col 0; len 2; (2):  c1 03
    col 1; len 6; (6):  02 c0 05 16 00 00
    col 2; len 6; (6):  02 c0 05 16 00 07
    col 3; len 1; (1):  02
    row#5[16094] flag: -----, lock: 2
    col 0; len 2; (2):  c1 04 age = 3
    col 1; len 6; (6):  02 c0 05 16 00 08
    col 2; len 6; (6):  02 c0 05 16 00 0f
    col 3; len 1; (1):  01   这回我们可以确定,这个值是相对位置而不是rowid的后两位了。参考上面的rowid值,age=3的记录是这个索引段的第二条记录
    row#6[16222] flag: ---D-, lock: 2
    col 0; NULL
    col 1; NULL
    col 2; NULL
    col 3; NULL
    ----- end of leaf block dump -----
    End dump data blocks tsn: 11 file#: 11 minblk 1352 maxblk 1352


    __________________
    学习ORACLE最大的障碍是什么——浮躁

    http://yangtingkun.itpub.net

    个人BLOG文章索引:http://www.itpub.net/699527.html

    11g的一点研究:http://www.itpub.net/852861.html
    只看该作者    顶部
    离线 yangtingkun
    版主


    精华贴数 12
    个人空间 69126
    技术积分 49460 (15)
    社区积分 3213 (554)
    注册日期 2001-12-29
    论坛徽章:162
    现任管理团队成员BLOG每日发帖之星2010新春纪念徽章2010年世界杯参赛球队:意大利BLOG每日发帖之星BLOG每日发帖之星
    BLOG每日发帖之星BLOG每日发帖之星BLOG每日发帖之星2010新春纪念徽章  

    发表于 2004-7-6 10:37 


    QUOTE:
    最初由 grassbell 发布
    是的,我也发现这个问题。比如你再插入2,这个值就变成 01
    但是再插入2,就会使用bitmap了。

    还有一个问题就是,begin/end rowid 的范围是怎么定的?
    比如有的例子中是02 c0 05 16 00 00~~ 02 c0 05 16 00 17
    而有的是        00 c0 7e 03 00 00~~ 00 c0 7e 03 00 0f


    呵呵,你的回帖很快啊。

    范围的大小biti已经说过了。
    我大致总结了一下。在处理的时候首先会试图重用以前索引段中的空闲空间,如果空闲空间不够用或者没有空闲空间的话,会分配新的空间。

    新的空间范围为=floor((处理行数-剩余空间可存放的记录数)/8)


    __________________
    学习ORACLE最大的障碍是什么——浮躁

    http://yangtingkun.itpub.net

    个人BLOG文章索引:http://www.itpub.net/699527.html

    11g的一点研究:http://www.itpub.net/852861.html
    只看该作者    顶部
    相关内容


    CopyRight 1999-2006 itpub.net All Right Reserved.
    北京皓辰网域网络信息技术有限公司. 版权所有
    E-mail:Webmaster@itpub.net
    网站律师 隐私政策 知识产权声明
    京ICP证:060528号 联系我们