【难点攻克技术系列】「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重、查找和排序

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 【难点攻克技术系列】「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重、查找和排序

BitMap(位图)的介绍


BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射,其中数据库中有一种索引就叫做位图索引。


在具有性能优化的数据结构中,大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美。但是数据量大了,内存就不够了。此外,可以使用类似外排序来解决问题的,由于要走IO所以时间上又不行。


所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以节省。




BitMap(位图)的应用


  • 1)可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下。
  • 2)去重数据而达到压缩数据




BitMap(位图)的原理


上面说了BitMap的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据。



BitMap(位图)的案例


假设有这样一个需求:在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存


在Java中,int占4字节,1字节=8位(1 byte = 8 bit)


  • 如果每个数字用int存储,那就是20亿个int,因而占用的空间约为  (2000000000*4/1024/1024/1024)≈7.45G
  • 如果按位存储就不一样了,20亿个数就是20亿位,占用空间约为  (2000000000/8/1024/1024/1024)≈0.233G

如何表示一个数呢


每一位表示一个数,0表示不存在,1表示存在,这正符合二进制


这样可以很容易表示{1,2,4,6}这几个数:

image.png

计算机内存分配的最小单位是字节,也就是8位,那如果要表示{12,13,15}怎么办呢?当然是在另一个8位上表示了:

image.png

这样的话,好像变成一个二维数组了


1个int占32位,那么我们只需要申请一个int数组长度为 int tmp[1+N/32] 即可存储,其中N表示要存储的这些数中的最大值,于是乎:


  • tmp[0]:可以表示0~31
  • tmp[1]:可以表示32~63
  • tmp[2]:可以表示64~95


如此一来,给定任意整数M,那么M/32就得到下标,M%32就知道它在此下标的哪个位置。



添加


怎么把一个数放进去呢?例如,想把5这个数字放进去,怎么做呢?


首先,5/32=0,5%32=5,也是说它应该在tmp[0]的第5个位置,那我们把1向左移动5位,然后按位或

image.png



换成二进制就是

image.png


这就相当于 86 | 32 = 118

86 | (1<<5) = 118
b[0] = b[0] | (1<<5)
复制代码


要想插入一个数,将1左移带代表该数字的那一位,然后与原数进行按位或操作


简化一下,就是 86 + (5/8) | (1<<(5%8))

因此,公式可以概括为:p + (i/8)|(1<<(i%8)) 其中,p表示现在的值,i表示待插入的数



清除


如果要清除该怎么做呢?


还是上面的例子,假设我们要6移除,该怎么做呢?

image.png

从图上看,只需将该数所在的位置为0即可


1左移6位,就到达6这个数字所代表的位,然后按位取反,最后与原数按位与,这样就把该位置为0了


b[0] = b[0] & (~(1<<6))

b[0] = b[0] & (~(1<<(i%8)))




查找


每一位代表一个数字,1表示有(或者说存在),0表示无(或者说不存在)。通过把该为置为1或者0来达到添加和清除的效果,那么判断一个数存不存在就是判断该数所在的位是0还是1

假设,我们想知道3在不在,那么只需判断 b[0] & (1<<3) 如果这个值是0,则不存在,如果是1,就表示存在。




Bitmap快速排序


假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复),我们就可以采用Bit-map的方法来达到排序的目的。要表示8个数,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0,然后将对应位置为1。最后,遍历一遍Bit区域,将该位是一的位的编号输出(2,3,4,5,7),这样就达到了排序的目的,时间复杂度O(n)。




优点:


  • 运算效率高,不需要进行比较和移位;
  • 占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M



缺点:


  • 所有的数据不能重复。即不可对重复的数据进行排序和查找。
  • 只有当数据比较密集时才有优势



Bitmap快速去重


  • 20亿个整数中找出不重复的整数的个数,内存不足以容纳这20亿个整数。


  • 首先,根据“内存空间不足以容纳这05亿个整数”我们可以快速的联想到Bit-map。下边关键的问题就是怎么设计我们的Bit-map来表示这20亿个数字的状态了。其实这个问题很简单,一个数字的状态只有三种,分别为不存在,只有一个,有重复。因此,只需要2bits就可以对一个数字的状态进行存储了,假设我们设定一个数字不存在为00,存在一次01,存在两次及其以上为11。那我们大概需要存储空间2G左右。


  • 接下来的任务就是把这20亿个数字放进去(存储),如果对应的状态位为00,则将其变为01,表示存在一次;如果对应的状态位为01,则将其变为11,表示已经有一个了,即出现多次;如果为11,则对应的状态位保持不变,仍表示出现多次。


  • 最后,统计状态位为01的个数,就得到了不重复的数字个数,时间复杂度为O(n)。




快速查找


int数组中的一个元素是4字节占32位,那么除以32就知道元素的下标,对32求余数(%32)就知道它在哪一位,如果该位是1,则表示存在.



Bitmap的场景总结


  • Bitmap主要用于快速检索关键字状态,通常要求关键字是一个连续的序列(或者关键字是一个连续序列中的大部分), 最基本的情况,使用1bit表示一个关键字的状态(可标示两种状态),但根据需要也可以使用2bit(表示4种状态),3bit(表示8种状态)。


  • Bitmap的主要应用场合:表示连续(或接近连续,即大部分会出现)的关键字序列的状态(状态数/关键字个数  越小越好)。


  • 32位机器上,对于一个整型数,比如int a=1 在内存中占32bit位,这是为了方便计算机的运算。但是对于某些应用场景而言,这属于一种巨大的浪费,因为我们可以用对应的32bit位对应存储十进制的0-31个数,而这就是Bit-map的基本思想。Bit-map算法利用这种思想处理大量数据的排序、查询以及去重。




参考资料


blog.csdn.net/qq_41369135…




相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
1月前
|
数据库 数据库管理 索引
索引在提高查询性能方面的优势体现在哪些方面?
索引在提高查询性能方面具有多方面的显著优势
|
2月前
|
SQL 缓存 分布式计算
C#如何处理上亿级数据的查询效率
C#如何处理上亿级数据的查询效率
47 1
|
4月前
|
数据可视化 数据挖掘 Python
揭秘数据排序的神秘面纱:如何用DataFrame排序和排名洞悉数据背后的秘密?
【8月更文挑战第22天】DataFrame排序和排名是数据分析的关键步骤,尤其在使用Python的Pandas库处理表格数据时尤为重要。通过对DataFrame使用`sort_values()`方法可实现基于一列或多列的灵活排序,而`rank()`方法则能轻松完成数据排名。例如,对学生信息DataFrame按分数排序及排名,或先按年龄排序再按分数排名,均可快速洞察数据模式与异常值,适用于金融分析和教育研究等多个领域。掌握这些技术有助于提高数据分析效率并深入理解数据。
57 1
|
7月前
|
SQL 存储 分布式计算
奇思妙想的SQL|去重Cube计算优化新思路
本文主要分享了作者在蚂蚁集团高管数据链路改造升级过程中,针对去重Cube的优化实践。
850 48
|
4月前
|
SQL 关系型数据库 MySQL
SQL索引构建与优化的神奇之处:如何用高效索引让你的数据检索飞起来?
【8月更文挑战第31天】在现代软件开发中,数据库索引对于提升查询性能至关重要。本文详细介绍了SQL索引的概念、构建方法及优化技巧,包括避免不必要的索引、使用复合索引等策略,并提供了实用的示例代码,如 `CREATE INDEX index_name ON table_name (column_name, another_column_name);`。通过遵循这些最佳实践,如了解查询模式和定期维护索引,可以大幅提高数据检索效率,从而增强应用程序的整体性能。
145 0
|
5月前
|
数据采集 数据挖掘 数据处理
数据转换与聚合,Python的双刃剑!精准切割,深度挖掘,数据世界任你遨游!
【7月更文挑战第19天】Python的Pandas库是数据科学家处理数据的得力工具,它在数据转换和聚合上的功能强大。例如,使用Pandas的`to_datetime`函数能统一日期格式,而`groupby`配合`agg`则可按类别聚合数据,进行统计分析。通过这些方法,可以有效地清洗数据、提取关键信息,助力数据驱动的决策。
48 2
|
6月前
|
存储 算法 安全
基于Guava布隆过滤器的海量字符串高效去重实践
基于Guava布隆过滤器的海量字符串高效去重实践
|
7月前
|
存储 监控 数据库
改良海量数据存储的若干的手段-转变数据垃圾为黄金
改良海量数据存储的若干的手段-转变数据垃圾为黄金
62 0
|
7月前
|
存储 新零售 监控
挖掘业务场景的存储更优解
挖掘业务场景的存储更优解
101 0
|
存储 关系型数据库 MySQL
MySQL索引探秘:加速数据检索的必备利器
MySQL索引探秘:加速数据检索的必备利器
274 0