查看: 39329|回复: 44

[精华] bitmap 的一点探究

[复制链接]
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
发表于 2003-4-19 16:15 | 显示全部楼层 |阅读模式
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
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
 楼主| 发表于 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 的时候情形更为复杂,暂时不予讨论了

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
 楼主| 发表于 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 是否合适就值得考虑了

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
21
授权会员
日期:2005-10-30 17:05:332012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:36马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:11:36
发表于 2004-7-5 16:03 | 显示全部楼层
本想写一写对bitmap的看法,搜了一下,看到biti早在我还没开始学习oracle的时候,就已经写过了!

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
发表于 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表示了这个段中的第一条记录[/COLOR]
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

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
21
授权会员
日期:2005-10-30 17:05:332012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:36马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:11:36
发表于 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

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
发表于 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位置表示法[/COLOR]
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的最后两位。[/COLOR]

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

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
21
授权会员
日期:2005-10-30 17:05:332012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:36马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:11:36
发表于 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

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
发表于 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[/COLOR]
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的记录是这个索引段的第二条记录[/COLOR]
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

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
发表于 2004-7-6 10:37 | 显示全部楼层
最初由 grassbell 发布
[B]是的,我也发现这个问题。比如你再插入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 [/B]


呵呵,你的回帖很快啊。

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

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

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表