海量数据解决方案Bitmap

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://gudepeng.github.io/note/2019/12/28/bitmap/

一.Bitmap简介

1:Bitmap算法又名位图算法,其原理是,使用下标代替数值或特定的意义,使用这个位为0或者1代表特性是否存在。
2:Bitmap算法具有效率高,节省空间的特点,适用于对大量数据进行去重,查询等,因为bit在计算机内只占一个bit,而int类型占用32个bit,所以空间节省了32倍。

二.使用场景

假如有一批人群信息,要给这批人群打上标签,例如你要给某些人打上会员的标签,并且要打上30天内购买过商品的人。你可能会在每个人身上打上标签,这样你在获取一个会员集合的时候需要遍历每一个人判断他是否包含会员标签,这样的计算量太大。
你可以换一种思路,我们有10个人,这样我们就会定义一个10位的数组,我们可以把人群按照自增类型设定每个人的id(从0开始),然后每一位对应一个人,用0,1去判断这个人是否有这个标签。
会员标签 |0|1|1|1|0|0|0|1|0|0|
这样我们就可以非常直观的查询到,我们id为1,2,3,7的人事会员。接下来我们继续打一个30天内购买过商品的人
30天内购买过商品的人 |1|1|0|0|0|0|0|0|0|0|
可以直观的看褚30天内购买过商品的人id为0,1。那么我们想要找出30天内购买过商品的会员,我们只需要做与运算(&)。
会员标签 |0|1|1|1|0|0|0|1|0|0|
30天内购买过商品的人 |1|1|0|0|0|0|0|0|0|0|
30天内购买过商品的会员 |0|1|0|0|0|0|0|0|0|0|
那么我们想要找出30天内购买过商品或者是会员,我们只需要做或运算(|)。
会员标签 |0|1|1|1|0|0|0|1|0|0|
30天内购买过商品的人 |1|1|0|0|0|0|0|0|0|0|
30天内购买过商品的会员 |1|1|1|1|0|0|0|1|0|0|
那么你一定会说,我创建一个map就可以搞定这个,为什么要使用bitmap呢。
因为在计算机中, 1个int占4字节即32位,而使用Bitmap的话,只需要1/32的内存。
你可能会说,那么我有一个10万的人群,那么我有多少个标签就需要开辟多少个10万位的bit,但是假如我只有一个人符合这个标签就会浪费很多资源,接下来我会在具体的使用方法中告诉大家这个问题是怎么解决的。

三.具体实现方法

在这里我们主要讲解两种主要的使用方法,第一个是EWAHCompressedBitmap(谷歌对Bitmap的实现),第二个是RoaringBitmap(这个也是大多数主流应用所使用的,例如Spark,Hive,Kylin等)。

1.EWAHCompressedBitmap

EWAH是把Bitmap存褚在一个long数组中,每个元素可以看作为一个64位的二进制数,在EWAH中也叫做word,EWAH初始化是4个word,当所有word都被占用后,就会进行扩容。当添加的数据跨度很大的时候,EWAH会创建一个RLW(Running Length word),RLW被分为两部分,低32位标识当前word跨越了多少个空word,高32位标识当前RLW后面有多少个连续的word。这样就解决了,跨度很大而开辟大量空间的问题。

2.RoaringBitmap

Roaring Bitmap是将32位的整数分割成2的16次方个整数的数据块,来共享相同的16个最高有效位。使用专门的容器来保存它们的16个最低有效位。
当一个数据块整数不超过4096个时,使用一个16位整数的有序数组(在java中使用short类型数组)。当超过4096个整数时,我们使用216位的位图(在java中使用long类型数组)。因此我们有两种类型的容器,对于稀疏数据块的数组容器(ArrayContainer)和对于密集数据块的位图容器(BitmapContainer)。阈值4096保证容器的级别,每个整数使用不超过16比特。使用位图容器时,使用216来表示超过4096(=212)个整数,少于16比特/整数(216 / 2^12 = 2^4 = 16,如果值都充满long数组,最理想情况下1比特/整数)。使用数组容器时使用精确的16比特/整数。
为什么选择4096这个阈值呢?因为小于4096时,位图容器可能大于16比特/整数,大于4096时,数组容器会超过216(212 * 16 = 216),占用空间显然超过216这个低16位表示的数的容量。一句话,整数基数较小时,使用数组更省空间,基数较大时,使用bitmap更省空间。
这些容器保存在一个共享16个最高有效位的动态数组中:它们作为一级索引。使用数组保证高16位有序。我们认为一级索引一般很小。当n=1 000 000时,它至多包含16个实体。因此它应该保存在CPU缓存中。容器本身不应该使用超过8KB。
下面是一篇论性能对比论文:
http://db.ucsd.edu/wp-content/uploads/2017/03/sidm338-wangA.pdf

四.RoaringBitmap使用方式

1.maven引入

<dependencies>
    <dependency>
        <groupId>org.roaringbitmap</groupId>
        <artifactId>RoaringBitmap</artifactId>
        <version>0.8.12</version>
    </dependency>
</dependencies>

2.方法使用

public static void main(String[] args) {
    RoaringBitmap rb = RoaringBitmap.bitmapOf(1,2,3,4,7,33,55);
    //select 返回第几位的值
    System.out.println(rb.select(1));
    //rank 返回小于等于参数的值得个数
    System.out.println(rb.rank(55));
    //contains 是否包含参数
    System.out.println(rb.contains(56));
    //contains 是否包含参数
    System.out.println(rb.contains(5L,56L));
    //add 添加从左闭到右开区间内的值
    rb.add(10L,15L);
    System.out.println(rb);

    RoaringBitmap rb1 = RoaringBitmap.bitmapOf(2,3,4,44);
    System.out.println(rb1);
    //取两个bitmap的并集
    RoaringBitmap rb1or2=RoaringBitmap.or(rb,rb1);
    System.out.println(rb1or2);
    //取两个bitmap的交集
    RoaringBitmap rb1and2=RoaringBitmap.and(rb,rb1);
    System.out.println(rb1and2);
    rb.and(rb1);
    System.out.println(rb);
    //获取第一位
    System.out.println(rb.first());
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容