最近在项目中遇到一个情况,SQL的where条件设计某一列为人名信息,分布规律较差,筛选率不高,因此选择了位图索引进行创建。语句类似为:

create bitmap  index "DM_TEST" on "SYSDBA"."TEST("NAME") storage(initial 1,next 1,minextents 1);

创建完成后,使用语句查询,速度从原来的2s降低到20ms效果非常显著。

但好景不长,在接下来的测试过程中发现了奇怪的现象,对系统进行INSERT场景的测试过程中,出现了死锁情况。而时间节点正好是创建为这个位图索引的时间点。于是将位图索引去掉后,发现死锁的情况消失。判定问题就在位图索引这里。

这是为什么呢?首先我们来看下位图索引的原理:

位图索引就是用位图表示的索引,对列的每个键值建立一个位图。相对于BTree索引,占用的空间非常小,创建和使用非常快。位图索引由于只存储键值的起止Rowid和位图,占用的空间非常少。如test表中有state这样一列,10行数据如下:

mysql 有没有位图索引 mysql创建位图索引_键值


那么会建立三个位图,如下:

mysql 有没有位图索引 mysql创建位图索引_位图_02


可以想象到,当对一条数据进行增删改后,上述三个KEY对应的值都会做修改。如果开始描述的问题,当有大概500个人名的表中做大量的INSERT,那么一次就会对KEY造成500次的数据修改。批量时就是成500*N倍修改,数据量可想而知!

因此建议位图索引的使用范围为:
1.适合决策支持系统;
2.当select count(XX) 时,可以直接访问索引中一个位图就快速得出统计数据;
3.当根据键值做and,or或 in(x,y,…)查询时,直接用索引的位图进行或运算,快速得出结果行数据。

不建议使用的范围为:
1.不适合键值较多的列(重复值较少的列);
2.不适合update、insert、delete频繁的列,代价很高。