BitSet索引学习
近我们在使用druid的过程中使用了BitSet索引。这个邮件是我之前总结的JDK的BitSet实现。非常巧妙。我在这里可以进一步分享一下。
目录
一.总结一下JDK的BitSet
二.Roaring BitSet
三.留些思考问题
四.我的要求
一.总结一下JDK的BitSet
1.long是8个字节,也就是64bit。64个bit可以保存64个数字。
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 表示0
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 表示1
依次类推
2.我们可以将数字[0,n)划分成为
[0,64),[64,2*64),[2*64,3*64).....
这样使用一个long[]数组就能够表示是否存在某个数字。
比如 8 我们可以放在long[0]这个long,使用bit
00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000 表示8
二.Roaring BitSet
roaring bitset 是JDK BitSet的升级版本。他考虑了数据的稀疏和稠密这两种情况,采用了灵活的数据结构,来降低内存使用。同时,他也考虑了CPU的缓存,使用佳的内存大小来存储数据。这两方面的优化,让BitSet存储下降,同时运算能力提升。
1.short是2个字节,也就是16bit,long是8个字节,也就是64bit。
2.我们可以将数字[0,n)划分成为
[0,2^16),[2^16,2*2^16),[2*2^16,3*2^16)...
3.对于一个32bit的数字,我们可以将其分为高16位和后16位两部分。相同高位的数据保存在同一个container里面。
4.container会根据数据的稀疏还是稠密选择不一样的数据结构。
当相同高位数据对应的container保存的数据少于4096个时,container采用 short[]数组进行数据的保存,当数据超过4096后采用BitMapContainer进行保存。
bitmapcontainer的数据结构是 long[]数据,他的长度是固定的,1024。1024个long就能保存1024*64个关键字,其大小正好是8 kb。
当同一个高16位key对应的数据少于4096时
当保存的数据超过4096时
三.留些思考问题
1.当存储1~65536个数据时,是JDK的BitSet省内存还是Roaring BitSet省内存?请评估内存占用量。
2.当存储1~10000000000个数据中的随机数据,随机数据取1000000个时,JDK BitSet和Roaring BitSet那个性能更佳?请评估内存占用量。
这些问题需要思考,我还要求要对RLE类型BitMap有深入理解。我不希望只知道写的慢,或者程序告诉我们的,这个数据结构存了什么数据,然后他占用了多少内存。我希望我们能算出来。
四.我的要求
我们是在做大数据。我们要对内存敏感。同时我们要对数据的规律敏感。我们必须要掌握核心技能,才能做到了然于胸。
相关文章