参考 https://www.cnblogs.com/lbser/p/3322630.html https://blog.csdn.net/catoop/article/details/111689777
有张表名为table的表,由三列组成,分别是姓名、性别和婚姻状况,其中性别只有男和女两项,婚姻状况由已婚、未婚、离婚这三项,该表共有100w个记录。现在有这样的查询: select * from table where Gender=‘男’ and Marital=“未婚”;
姓名 | 性别 | 婚姻状况 |
---|---|---|
张三 | 男 | 已婚 |
李四 | 女 | 已婚 |
王五 | 男 | 未婚 |
赵六 | 女 | 离婚 |
孙七 | 女 | 未婚 |
… | … | – |
还是需要取出一半的数据
, 因此完全没有必要。相反,如果某个字段的取值范围很广,几乎没有重复,比如身份证号,此时使用B树索引较为合适
。事实上,当取出的行数据占用表中大部分的数据时,即使添加了B树索引,数据库如oracle、mysql也不会使用B树索引,很有可能还是一行行全部扫描。
如果用户查询的列的基数非常的小
, 即只有的几个固定值,如性别、婚姻状况、行政区等等。要为这些基数值比较小的列建索引,就需要建立位图索引
。
对于性别这个列,位图索引形成两个向量,男向量为10100…,向量的每一位表示该行是否是男,如果是则位1,否为0,同理,女向量位01011。
RowId | 1 | 2 | 3 | 4 | 5 | … |
---|---|---|---|---|---|---|
男 | 1 | 0 | 1 | 0 | 0 | … |
女 | 0 | 1 | 0 | 1 | 1 | … |
对于婚姻状况这一列,位图索引生成三个向量,已婚为11000…,未婚为00100…,离婚为00010…。
RowId | 1 | 2 | 3 | 4 | 5 | … |
---|---|---|---|---|---|---|
已婚 | 1 | 1 | 0 | 0 | 0 | … |
未婚 | 0 | 0 | 1 | 0 | 1 | … |
离婚 | 0 | 0 | 0 | 1 | 0 | … |
当我们使用查询语句“select * from table where Gender=‘男’ and Marital=“未婚”;”的时候 首先取出男向量10100…,然后取出未婚向量00100…,将两个向量做and操作,这时生成新向量00100…,可以发现第三位为1,表示该表的第三行数据就是我们需要查询的结果。
RowId | 1 | 2 | 3 | 4 | 5 | … |
---|---|---|---|---|---|---|
男 | 1 | 0 | 1 | 0 | 0 | … |
and | ||||||
未婚 | 0 | 0 | 1 | 0 | 1 | … |
结果 | 0 | 0 | 1 | 0 | 0 | … |
BitMap索引适用场景
建在值重复度高的列上
,GP手册建议在100到100,000之间,如:职业、地市
等。重复度过高则对比其他类型索引没有明显优势;重复度过低,则空间效率和性能会大大降低。特定类型的查询
例如count、or、and等逻辑操作
因为只需要进行位运算
。如:通过多个条件组合查询,select count(*) from table where city = ’南京市’ and job = ’医生’ and phonetype = ‘iphone’ and gender =’男’。类似这种场景,如果在每个查询条件列上都建立了bitmap索引,则数据库可以进行高效的bit运算,精确定位到需要的数据,减少磁盘IO。并且筛选出的结果集越小,bitmap索引的优势越明显。适用于即席查询、多维分析等OLAP场景
。如果有一张表有100列,用户会使用其中的20 个列作为查询条件(任意使用这20个列上的N的列),几乎没有办法创建合适的 b-tree 索引。但是在这些列上创建 20 个 bitmap 索引,那么所有的查询都可以应用到索引。BitMap索引不适用场景
值重复度低
的列,如:身份证号、手机号码等。重复度过低
的列,如:性别,可以建立bitmap索引,但不建议单独作为查询条件使用,建议与其他条件共同过滤。更新修改
的列。举个例子,有这样一个字段busy,记录各个机器的繁忙与否,当机器忙碌时,busy为1,当机器不忙碌时,busy为0。
这个时候有人会说使用位图索引,因为busy只有两个值。好,我们使用位图索引索引busy字段!假设用户A使用update更新某个机器的busy值,比如update table set table.busy=1 where rowid=100;,但还没有commit,而用户B也使用update更新另一个机器的busy值,update table set table.busy=1 where rowid=12; 这个时候用户B怎么也更新不了,需要等待用户A commit。
原因:用户A更新了某个机器的busy值为1,会导致所有busy为1的机器的位图向量发生改变
,因此数据库会将busy=1的所有行锁
定,只有commit之后才解锁。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/226937.html原文链接:https://javaforall.cn