BitMap介绍与应用

文章目录

  • BitMap
    • BitMap介绍
      • BitMap 结构
      • RoaringBitmap
    • 常见BitMap
      • Java中的BitSet
      • Redis中的BitMap
      • ClickHouse中的BitMap
    • BitMap应用案例
      • 人群圈选

BitMap

场景一:(大部分开发面试都会遇到的一个问题)

有10亿个用户id (int类型),判断用户是否登录?(限制内存)

🤔 10亿个int类型,10亿 × 4 = 40亿byte = 4 GB,如何既要保证速度,又要保证占用内存呢?

场景二:

短视频平台中有十亿+用户,广告主想要精准投放流量,如何进行人群的圈选呢?

BitMap介绍

bit(位)map(地图)被叫做位图,其实理解其原理之后,可能叫位(bit)映射(map)更贴切一些。

BitMap比较适合通过比较小的内存解决大量数字的去重、排序和判存问题。

BitMap 结构

用场景一的问题举例:BitMap解决思路就是构建一个bit数组,bit每一位只能表示1或者0,其中数组的索引值映射到userId,当前索引上的数字是1的时候代表对应的userId已登录,是0的时候代表userId未登录。所以,逐行读取文件中的userid并给bit数组赋值,最终通过该bit数组就可以实现去重、排序和判存了。
image-20240112115256884.png
(上图中的用户34 就是已登录的)

假设每个位使用1比特(bit)来表示,那么十亿级别的位图将有10^9个位。由于每个字节(byte)包含8个位,我们可以将位数除以8来得到字节数。

总字节数 = 10^9 / 8 = 125,000,000 字节

将字节数转换为更常见的单位,可以得到以下结果:

  • 125,000,000 字节 = 125 兆字节(MB)

位图也不是万能的,还是上述的题目,如果需要统计出每一个userId的出现次数,位图这种通过1和0标识有和无的方式就无法表达这个业务含义了。当位图比较稀疏的时候,也可能浪费空间,比如文件中就1和1000000000这两个userid,那么为为了使用位图而开辟的bit数组大小已经远超过两个int数字所使用的空间了。

RoaringBitmap

RoaringBitmap可以认为是BitMap的另外一种实现,该实现方式中考虑了数据量的多少与存储空间的平衡问题。将32的数字分为高16位和低16位,其中低16位根据数据量的多少,可以通过三种数据结构来实现:ArrayContainerBitMapContainerRunContainer,其目的就是尽量节约存储空间。

  • 数组容器(Array Container) :这种容器使用一个数组来存储整数,适用于稀疏数据的情况,即数据之间的间隔较大。例如,如果一个容器内的整数数量小于4096,就使用数组容器来存储,因为在这种情况下,使用数组容器比使用位图容器更节省空间。
  • 位图容器(Bitmap Container) :位图容器使用一个长度为65536的位数组(bit array)来存储数据,适用于稠密数据的情况,即数据之间的间隔较小。例如,如果一个容器内的整数数量大于4096,就使用位图容器来存储,因为在这种情况下,使用位图容器比使用数组容器更节省空间。
  • 运行长度编码容器(Run Container) :运行长度编码(Run-length Encoding,RLE)是一种简单的数据压缩算法,适用于连续重复数据的情况。在 Roaring Bitmap 中,如果一系列连续的整数都存在于位图中,那么可以使用一个运行长度编码容器来存储这些连续的整数的起始值和长度,从而节省空间。

RoaringBitmap 根据实际的数据情况,动态地选择最适合的容器类型,从而实现了既高效的数据存储,又快速的数据查询。在做位图计算(AND、OR、XOR)时,RoaringBitmap提供了相应的算法来高效地实现在多个容器之间的运算,使得RoaringBitmap无论在存储和计算性能上都表现优秀。

image.png

常见BitMap

Java中的BitSet

BitSet 是 Java 中的一个类,用于表示位集合(bit set)。它提供了一种有效地存储和操作位(布尔值)的方式。

下面是一个示意图,展示了 BitSet 的基本结构:

+---------+---------+---------+---------+---------+---------+---------+---------+
| 位索引:  |    0    |    1    |    2    |    3    |    4    |    5    |    6    |
+---------+---------+---------+---------+---------+---------+---------+---------+
| 位值:    |   true  |   false |   true  |   false |   true  |   false |   false |
+---------+---------+---------+---------+---------+---------+---------+---------+

在上述示意图中,每个方框表示一个位,从左到右依次编号。位索引从 0 开始,表示每个位在 BitSet 中的位置。位值表示每个位的状态,可以是 true(被设置为 1)或 false(被设置为 0)。

BitSet 提供了一系列方法来操作位集合,例如:

  • set(int index):将指定索引位置的位设置为 true
  • clear(int index):将指定索引位置的位设置为 false
  • get(int index):获取指定索引位置的位的值。
  • size():获取位集合的大小(位的数量)。
  • length():获取位集合的长度(最高位的索引加 1)。
  • and(BitSet set):对当前位集合与另一个位集合执行逻辑与操作。
  • or(BitSet set):对当前位集合与另一个位集合执行逻辑或操作。
  • xor(BitSet set):对当前位集合与另一个位集合执行逻辑异或操作。

【例子】判断某个用户是否存在:

public class UserPresenceChecker {private BitSet userBitSet;public UserPresenceChecker() {userBitSet = new BitSet();}public void addUser(long userId) {userBitSet.set((int) userId);}public boolean isUserPresent(long userId) {return userBitSet.get((int) userId);}public static boolean checkUserPresence(long userId) {UserPresenceChecker presenceChecker = new UserPresenceChecker();// 假设有一亿用户存在for (int i = 0; i < 100000000; i++) {presenceChecker.addUser(i);}//模拟123不存在presenceChecker.userBitSet.set(123,false);return presenceChecker.isUserPresent(userId);}public static void main(String[] args) {long userId = 123;boolean isPresent = checkUserPresence(userId);if (isPresent) {System.out.println("用户 " + userId + " 存在");} else {System.out.println("用户 " + userId + " 不存在");}}
}

RoaringBitmap 在Java中也有实现,还提供了更多的逻辑运算方式。

Redis中的BitMap

Redis 的位图是一种特殊的字符串类型,可以用于存储和操作位级别的数据。

Redis 中的位图使用字节数组来表示,每个字节可以存储 8 个位。位图可以非常高效地进行位级别的操作,如设置位、获取位、计数位、位图之间的逻辑运算等。

以下是一些 Redis 中位图相关的命令:

  • SETBIT key offset value:设置指定偏移量上的位为指定值(0 或 1)。
  • GETBIT key offset:获取指定偏移量上的位的值。
  • BITCOUNT key [start end]:计算指定范围内的位为 1 的数量。
  • BITOP operation destkey key [key ...]:对多个位图进行逻辑运算,并将结果保存到目标位图中。
  • BITPOS key bit [start] [end]:查找指定位的第一个出现位置。

以下是一个示例,展示如何在 Redis 中使用位图:

# 设置位图
SETBIT mybitmap 0 1
SETBIT mybitmap 2 1
SETBIT mybitmap 5 1
​
# 获取位图
GETBIT mybitmap 0  # 返回 1
GETBIT mybitmap 1  # 返回 0
​
# 计算位图中位为 1 的数量
BITCOUNT mybitmap  # 返回 3
​
# 逻辑运算
SETBIT mybitmap2 1 1
SETBIT mybitmap2 3 1
BITOP AND mybitmap_and mybitmap mybitmap2  # 对两个位图进行 AND 运算,并将结果保存到 mybitmap_and 中
​
# 查找位为 1 的第一个出现位置
BITPOS mybitmap 1 0  # 返回 0
BITPOS mybitmap 1 1  # 返回 2

通过 Redis 的位图功能,你可以高效地存储和操作位级别的数据,例如记录用户的在线状态、统计用户活跃度、进行布隆过滤器等应用场景。

ClickHouse中的BitMap

😜3,2,1上链接!!!

https://clickhouse.com/docs/zh/sql-reference/functions/bitmap-functions

BitMap应用案例

人群圈选

如果有一张表,存储着每一个userid对应的常驻省和性别,如何从这张表中查出所有北京市男性用户的userId,并存储成一个人群包。

image.png

最简单直接的思路是select userId from table where sex = ‘男’ and province = ‘北京’,但是当满足条件的userId达到千万+级别时,通过SQL语句直接获取userId就不太合适,一是结果集比较大,二是执行比较耗时。

此时可以转换一个角度解决这类问题,如果表结构如下:

image.png
可以将不同标签值对应的userId列表转换成BitMap,再次筛选北京市男性用户的时候,直接将男BitMap与北京BitMap做交集即可,快速高效且节约大量的存储空间。

如图所示:

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773782.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自养号测评:如何助力跨境电商平台亚马逊、速卖通等店铺提升产品权重

对于卖家而言&#xff0c;爆款产品不仅意味着源源不断的流量&#xff0c;更是店铺销量增长的强有力保障。因此&#xff0c;多数卖家都积极学习如何打造爆款产品&#xff0c;特别是那些希望将店铺运营得风生水起的卖家们。那么&#xff0c;如何在激烈的市场竞争中打造出具有创新…

题解 P3295 【[SCOI2016]萌萌哒】

先引用一下这位大佬的题解&#xff0c;对此我再进行细化 题解 P3295 【[SCOI2016]萌萌哒】 - 洛谷专栏https://www.luogu.com.cn/article/it7foeu6并查集 首先是如何想出来需要并查集处理&#xff0c;下面是n8&#xff0c;第一组约束条件是[1,4]和[5,8]&#xff0c;如下图&am…

算法的时间复杂度与空间复杂度

俗话说“条条大路通罗马”&#xff0c; 我们在用算法解决某一个问题时&#xff0c;往往会存在多种解决方法&#xff0c;但正如道路有远近之分&#xff0c;不同的算法也应该是有优劣的。为了更加清晰的量化算法的优劣&#xff0c;我们就需要引入算法的时间复杂度与空间复杂度了。…

我的 Android 性能书上架了!内附书籍介绍

大家好&#xff0c;我是拭心。 很高兴地向大家宣布&#xff0c;我的新书《Android 性能优化入门与实战》上架了&#xff01; 点击下面的小程序进行购买&#xff1a; 封面介绍 这本书的封面来自之前的投票文章 # 投票啦&#xff01;最新安卓进阶书籍封面由你来定&#xff0c;从四…

设计模式深度解析:深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 ✨

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 开篇&#xff1a; 欢迎来到设计模式的神秘…

Unity 打包真机脚本丢失的问题

记录Bug Bug详情分析解决方案附录 Bug详情 项目中导入了UI Particle的Package,用于处理特效层级 unity 运行效果正常&#xff0c;打包真机后运行时发现特效并没有正确显示&#xff0c;真机Log如下图 需要接入查看真机Log工具的点这里 查看图中Log发现对应的Prefab上挂载的脚本…

【CSDN活动】程序员职业生涯的分水岭:年龄还是经验?

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 程序员职业生涯的分水岭&#xff1a;年龄还是经验&#xff1f;引言技术更新换代…

邮件营销工具的必备功能?如何选营销工具?

邮件营销工具的效果如何&#xff1f;营销工具怎么提升邮件营销&#xff1f; 一款优秀的邮件营销工具&#xff0c;不仅能够帮助企业高效地进行邮件发送&#xff0c;还能通过精准的数据分析和用户行为跟踪&#xff0c;提升营销效果。AokSend将探讨邮件营销工具的必备功能。 邮件…

Python机器学习赋能GIS:地质灾害风险评价的新方法论

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

鉴源论坛丨形式化工程方法之需求建模(下)

作者 | 杨坤 上海控安可信软件创新研究院系统建模组 版块 | 鉴源论坛 观模 引言&#xff1a;需求建模是一种从源头确保软件质量的重要手段。需求建模可分为需求规约和需求确认两个部分&#xff0c;前者通过严格设计的形式化语言精确地将需求文档转换为了形式化规约&#xff0…

PASSL代码解读[01] readme

介绍 PASSL 是一个基于 PaddlePaddle 的视觉库&#xff0c;用于使用 PaddlePaddle 进行最先进的视觉自监督学习研究。PASSL旨在加速自监督学习的研究周期&#xff1a;从设计一个新的自监督任务到评估所学的表征。 PASSL 主要特性&#xff1a; 自监督前沿算法实现 PASSL 实现了…

为什么requests不是python标准库?

在知乎上看到有人问&#xff1a;为什么requests不是python标准库&#xff1f; 这确实是部分人困惑的问题&#xff0c;requests作为python最受欢迎的http请求库&#xff0c;已经成为爬虫必备利器&#xff0c;为什么不把requests直接装到python标准库里呢&#xff1f;可以省去第…

学习使用xbox手柄控制小乌龟节点移动

使用xbox手柄控制小乌龟&#xff0c;首先要下载joy功能包&#xff0c;发布sensor_msgs话题也就是手柄和ros通信的话题。 下载的步骤就根据官方文档即可 joy/Tutorials/ConfiguringALinuxJoystick - ROS Wiki 这里我提供一下具体步骤 第一步 安装joy 首先安装对应系统版本的…

【第二部分--Python之基础】02

二、运算符与程序流程控制 1、运算符 1.1 算术运算符 算术运算符用于组织整数类型和浮点类型的数据&#xff0c;有一元运算符和二元运算符之分。 一元算术运算符有两个&#xff1a;&#xff08;正号&#xff09;和-&#xff08;负号&#xff09;&#xff0c;例如&#xff1…

SV-7041VP SIP塑料壳sip音箱支持POE供电(白色弧形)

SV-7041VP SIP塑料壳sip音箱支持POE供电 &#xff08;白色弧形&#xff09; 一、描述18123651365微信 SV-7041VP是深圳锐科达电子有限公司的一款壁挂式SIP网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可…

QT的 纯代码+注释 学习笔记

QT学习笔记链接 更新到数据库操作为止..ing

微信怎么恢复聊天记录?效果惊人的3个方法

微信作为我们日常生活中最常用的即时通讯工具之一&#xff0c;承载着我们与亲友之间的重要沟通记录。然而&#xff0c;不可避免地会遇到误删聊天记录的情况&#xff0c;可能是因为手误、设备问题或其他原因。 当我们发现重要的聊天记录不见了&#xff0c;往往会感到焦虑和困扰…

题目:求和(蓝桥真题)

问题描述&#xff1a; 解题思路&#xff1a; 暴力超时&#xff0c;S变换得S a1*(a2.....an) a2*(a3....an) .... an-1*an。因此只需要求出括号内前缀和再相加求和即可。时间复杂度大大减小。 注意点&#xff1a;ans和前缀和的大小要开long long。 题解&#xff1a; #includ…

openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint

文章目录 openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint252.1 功能描述252.2 语法格式252.3 参数说明252.4 示例 openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint 252.1 功能描述 指明scan使用的方法&#…

论文:Term-Weighting Approaches in Automatic Text Retrieval翻译笔记(自动文本检索中的术语加权方法)

文章目录 论文标题&#xff1a;自动文本检索中的术语加权方法摘要1. 自动文本分析2. 词权重规范3. 术语加权实验4 推荐4.1 查询向量4.2 文档向量 论文标题&#xff1a;自动文本检索中的术语加权方法 论文链接&#xff1a;https://www.cs.colostate.edu/~howe/cs640/papers/sal…