bitmap 常用的应用场景:
1.超大文件求交集:现有两个各有20亿行的文件,每一行都只有一个数字,求这两个文件的交集。
2.从海量电话号码中,统计不同号码的个数
3.统计APP的日活
4.bitmap实现大数据排序和去重
问题的引出:
有这样一种场景:一台普通PC,2G内存,要求处理一个包含40亿个不重复并且没有排过序的无符号的int整数,给出一个整数,问如果快速地判断这个整数是否在文件40亿个数据当中?
bitmap的建立:
40亿个int占(40亿*4(long int 是 4 byte))/1024(转为KB)/1024(转为MB)/1024(转为GB) 大概为14.9G左右,很明显内存只有2G,放不下,因此不可能将这40亿数据放到内存中计算。
ps:_1_KB=1024B;_1_MB=1024KB=1024×1024B;_1_B(byte,_字节_)= 8 _bit_(位)
一个int整数在Python中是占4个字节的即要32bit位,如果能够用一个bit位来标识一个int整数那么存储空间将大大减少,算一下40亿个int需要的内存空间为40亿/8/1024/1024大概为476.83 mb,这样的话我们完全可以将这40亿个int数放到内存中进行处理。
具体思路(BitMap思想):
1个int占4字节即4*8=32位,那么我们只需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据,其中N代表要进行查找的总数,tmp中的每个元素在内存在占32位可以对应表示十进制数0~31,所以可得到BitMap表:
tmp[0]:可表示0~31
tmp[1]:可表示32~63
tmp[2]可表示64~95
.......
那么接下来就看看十进制数如何转换为对应的bit位:
假设这40亿int数据为:6,3,8,32,36,......,那么具体的BitMap表示为:
(1)如何判断int数字放在哪一个tmp数组中:将数字直接除以32取整数部分(x/32),例如:整数8除以32取整等于0,那么8就在tmp[0]上,而32/32取整数=1,所以是在tmp[1],在Python直接就是32//32即可;
(2)如何确定数字放在32个位中的哪个位(从0开始):将数字mod32(x%32)。上例中我们如何确定8在tmp[0]中的32个位中的哪个位,这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。
综上:用num//32就得在哪个array里(某一行),具体是个下标用num%32(某一列)即可。
接下来的任务是怎么添加数字,和清除数字:
几个位运算的知识:
<< : 1的二进制表示:00000001,1<<3 的结构是00001000,就是把所有的位都往左边移动3位
1:运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
例如:3|5 即 00000011 | 0000 0101 = 00000111 因此,3|5的值得7。
&:运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两位同时为“1”,结果才为“1”,否则为0
例如:3&5 即 0000 0011& 0000 0101 = 00000001 因此,3&5的值得1。
~:取反
1:Clear方法(将数组的所有bit位置0)
比如要将当前4对应的bit位置0的话,只需要1左移4位取反与B[0] & 即可。
2:Add方法(将bit置1操作)
同样也很简单,要将当前4对应的bit位置1的话,只需要1左移4位与B[0] | 即可。
要查找当前4对应的bit位置是否为1,只需要1左移4位与B[0]& 即可。
整体的Python 代码:
下面的代码实现了bitmap实现大数据排序和去重
# -*- encoding:utf-8 -*-
import math
class Bitmap():
def __init__(self,max):
'确定所需数组个数'
self.size = math.ceil (max/ 32)
self.array = [0 for i in range(self.size)]
def bitindex(self,num):
'确定数组中元素的位索引'
return num % 32
def set_1(self,num):
'将元素所在的位置1'
elemindex = num // 32
byteindex = num % 32
ele = self.array[elemindex]
print(byteindex)
print('the original array ele {}'.format(format( ( ele), 'b').zfill(32)))
print('need insert byteindex {}'.format(format((1 << byteindex), 'b').zfill(32)))
self.array[elemindex] = ele | (1 << byteindex)
print('after insert byteindex {} \n'.format(format((self.array[elemindex]), 'b').zfill(32)))
def search_1(self,i):
'检测元素存在的位置'
elemindex = i // 32
byteindex = self.bitindex(i)
try:
self.array[elemindex]
except:
print(elemindex)
if self.array[elemindex] & (1 << byteindex):
return True
return False
if __name__ == '__main__':
Max = ord('z')
suffle_array = [x for x in 'qwelmfg']
result = []
bitmap = Bitmap(Max)
for c in suffle_array:
bitmap.set_1(ord(c))
for i in range(Max+1):
if bitmap.search_1(i):
result.append(chr(i))
print (u'原始数组为: %s' % suffle_array )
print (u'排序后的数组为: %s' % result)
bitmap在线上系统的应用:
id表示用户的id
如上图是一个数据表有四列,下面是一个简单查询,查询有性别和婚姻状况两个维度,性别有两个取值,婚姻状况有三个取值,BitMap首先会在维度里面构建BitMap,第一步如何构建性别的BitMap,对于性别这个列,位图索引形成两个向量,男向量为10100...,向量的每一位表示该行是否是男,如果是则位1,否为0,同理,女向量位01011。第二部构建婚姻状况的BitMap,婚姻状况这一列,位图索引生成三个向量,已婚为11000...,未婚为00100...,离婚为00010...。这样就构建完需要查询的BitMap,首先将性别为男的标签拿出来,然后将婚姻状况为未婚的标签拿出来求交,这样就定为下标为2,就查出满足需要的结果。
可以看出上图的列数随着用户增多不断加长,这个是最后有上限,也是不利于分布式计算,因此需要将id分区
海量数据处理之BitMap - moonandstar08 - 博客园www.cnblogs.com/moonandstar08/p/5236539.html
原网址: 访问
创建于: 2023-05-19 12:12:22
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论