一、背景
位图通常是查询加速过程中的常用的工具,一指没有仔细的研究过位图;现学习一下位图和位图的改进版RoaringBitMap;学习参考文章;
二、BitMap
BitMap的基本思想就是用一个bit位或多个bit位来标记某个元素对应的Value。而此Bit位即是对应的元素,value可以使用位的值(0或者1)来进行表示。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。
比如:用一个bit位来代表一个int整数是否出现,那么则只需要512M的存储,可以表示所有的整数是否出现;
2.1 BitMap使用限制条件
BitMap适用于数据比较密集的情况,比如题目:正整数的快速排序以及判断是否存在;正整数的去重以及计数。
2.2 举例说明
如果我们想快速排序{6,8,2,5,4},根据位图我们应该
三、RoaringBitMap
BitMap适合连续密集的正整数存储,对于稀疏的正整数存储,其性能在很多时候是没办法和int数组相比的,尤其是正整数跨度较大的场景;RoaringBitMap就是为了解决这个问题产生;
2.1 RoaringBitMap的数据结构
- 将32位的整数划分为高16位和低16位;高16位对应于2^16 ,即最多可能有65536个桶个桶;
- 低16位保存在对应桶的container中;主要包含ArrayContainer、BitMapContainer、RunLengthContainer三种,根据保存的数据情况保存到使用不同的Container;
这里跟HashMap使用链表还是红黑树保存一个道理;
- 首先当一个桶被创建时,第一个元素一定会被放在 ArrayContainer 中存储,因为此时的数据是绝对的稀疏;
- 后续的数据被放入到该桶时,RBM会计算 ArrayContainer 的数值个数,当数值个数超过4096时,就会将 ArrayContainer 转化为 BitmapContainer 存储,而超过4096即是RBM认为的数据密集的阈值
2.3 4096阈值的由来
ArrayContainer 的大小随元素个数的增加线性增长;而 BitmapContainer 则恒定为8KB。所以8KB就是临界点,而8KB对应的ArrayContainer存储的数据量恰恰是4096(存储的是无符号低16位,2 byte),这就是4096这个阈值的来历。
RunLengthContainer只有在手动调用runOptimize方法时才有可能产生,Run-Length编码并不是一直有效,具体可以参考文章