前言
日常业务中需要大量存储一些重复的字符串,例如每日签到用户、计算每日登录用户等、计算用户留存率等。字符串无论长短不仅会浪费大量的存储资源,而且读取查询也耗时耗资源;另外一个应用场景:利用 Bitmap 位图技术,可以解析前端圈群过程,对复杂人群圈选进行提速(实时数仓的用户标签圈选问题)。
一、BitMap(位图)
1.1 定义
在计算机中一个字byte)=8bit(位),位是 数据的最小表示单位,map一般是表示地图或者映射, bit +map 加一起叫作位图。一个bit有2种状态,0或者1。所以1个byte可以表示8位的 0000 0000 ->11111111
例如:添加[10,17,28] 这三个数到BitMap中,如下图,只需要将对应的那一位变为1即可。
本质上是一个二进制的数组,Bitmap最大支持的位数是2^32位,这可以节省很大的空间。例如将196660
这个数存起来,大概需要196660/8/1024 = 24K
的内存 【因为整个数组长度为196660】
另外一个例子:拿每日登录用户的场景举例,首先对用户id进行编号(offset)。
这样只需要每天创建一个只存储位的数组,比如2023-12-8日只有zhangsan和zhaoliu进行了登录,只需要一个4位的字节数组来进行存储,这样就达到了减少存储的目的。
1.2 应用场景
对于一些需要计算连续登录天数,某些int值是否存在等等场景是非常合适的。
1.3 缺陷
如果整个数组中,值的分布很稀疏 ,例如上述长度为196660
的数组,只表示了这一个值存在,使用Int
去存储的话,4Byte
就可以满足。在大量出现这种情况的时候,是非常消耗内存的。所以RoaringBitmap比起bitmap在这方面就更具有优势。BitMap最大的弊端是稀疏存储,如果数据很分散,基数很高,那么构建的BitMap将非常大,然后又会存储很多bit位是0的数据,造成严重的空间浪费。比如用户全量表中user_id的最大值达到13亿+,但是DAU(日活)在2500-3000w之间,如果不对user_id做任何处理,直接存入bitmap,那么就需要一个13亿+个bit位大小的BitMap。
二、RoaringBitMap(压缩位图)
2.1 定义
RoaringBitMap,是一种压缩位图,是对BitMap的改进,除了使用BitMap存储数据,还使用了array等数据结构,以达到压缩的目的。RoaringBitMap是如何做到压缩的?
现实的场景中,存储的数据并不是连续的,而是稀疏的,而且创建Bitmap的时候,长度必须是最大的offset的长度,例如我们有64个用户,那么创建的位数组就是64位。假如有1万个用户,但今天只有编号9999的用户登录了系统,还是要创建一个1万个Byte的数组,反而增加了内存的消耗。
为了更容易理解这个问题,还是以64位Bitmap为例,也就是最大支持存储64个用户,当只存储63时:
先创建了长度为64位的数组,只在63这个位置上的存储是有意义的,其他位置都是0,那这种情况可以进行优化。 把数组拆分成2组,1到32的用户存储到第1组,把33到64的用户存储到第二组。这个时候如果发现第一组的数组里全是0,那第一组就可以不用创建。最后就可以用一个32位大小的数组存储了64位的数据。
接下来更进一步,把64位的数组拆成每16个一组,那么只需要创建最后一个分组的数组,也就是16位的数组来达到进一步压缩的目的。最后的第4组的数据存储如下:
2.2 和BitMap的区别
(1)比BitMap更节省内存空间
- 把32位分为2^16个容器,只为用到的容器分配空间,解决了稀疏数据浪费空间的问题。
- 每个容器根据数据的稠密情况使用array或bitmap数据结构,节省每个容器占用的内存空间。
(2)比BitMap性能更高
- 因为不会开辟大量不用的内存,参与计算的内存块比较少,提升计算速度。
- 使用有序数组保存容器,在进行逻辑运算时(与或非)基本只需要计算相同索引的容器。
2.3 RoaringBitMap的作用
- 解决bitmap统计大数据尤其是稀疏数据浪费内存空间的问题;
- 解决bitmap内存空间无法收缩的问题:存储容器的array和ArrayContainer都是数组,支持清空和移除元素,但其空间释按照语言自身的GC机制处理。
总结:在离线标签,或者实时标签计算完成后,将某标签下的主键唯一id值【Int类型】用RoaringBitmap存储,这样在存储上就节省了大量的空间,同时在计算组合标签下的企业数量性能也会快速提升。
【用户留存分析专题模型设计】 中 就用到Bitmap位图 这种数据结构
参考文章:
通俗的理解Bitmap(位图)和RoaringBitmap(压缩位图) - 简书RoaringBitmap和Bitmap的区别与原理_一文读懂比bitmap有更好性能的roaring bitmap-CSDN博客
https://blog.51cto.com/u_15714439/6146579