转自:https://www.seoxiehui.cn/article-45186-1.html

需求:

  为满足用户标签的统计需求,小灰利用Mysql设计了如下的表结构,每一个维度的标签都对应着Mysql表的一列:要想统计所有90后的程序员该怎么做呢

两个月之前——

为满足用户标签的统计需求,小灰利用Mysql设计了如下的表结构,每一个维度的标签都对应着Mysql表的一列:

要想统计所有90后的程序员该怎么做呢?

用一条求交集的SQL语句即可:

Select count(distinct Name) as 用户数 from table whare age = '90后' and Occupation = '程序员' ;

要想统计所有使用苹果手机或者00后的用户总合该怎么做?

用一条求并集的SQL语句即可:

Select count(distinct Name) as 用户数 from table whare Phone = '苹果' or age = '00后' ;

两个月之后——

———————————————

1. 给定长度是10的bitmap,每一个bit位分别对应着从0到9的10个整型数。此时bitmap的所有位都是0。

2. 把整型数4存入bitmap,对应存储的位置就是下标为4的位置,将此bit置为1。

3. 把整型数2存入bitmap,对应存储的位置就是下标为2的位置,将此bit置为1。

4. 把整型数1存入bitmap,对应存储的位置就是下标为1的位置,将此bit置为1。

5. 把整型数3存入bitmap,对应存储的位置就是下标为3的位置,将此bit置为1。

要问此时bitmap里存储了哪些元素?显然是4,3,2,1,一目了然。

Bitmap不仅方便查询,还可以去除掉重复的整型数。

1. 建立用户名和用户ID的映射:

2. 让每一个标签存储包含此标签的所有用户ID,每一个标签都是一个独立的Bitmap。

3. 这样,实现用户的去重和查询统计,就变得一目了然:

1. 如何查找使用苹果手机的程序员用户?

2. 如何查找所有男性或者00后的用户?

一周之后......

我们以上一期的用户数据为例,用户基本信息如下。按照年龄标签,可以划分成90后、00后两个Bitmap:

用更加形象的表示,90后用户的Bitmap如下:

这时候可以直接求得90后的用户吗?直接进行非运算?

显然,非90后用户实际上只有1个,而不是图中得到的8个结果,所以不能直接进行非运算。

同样是刚才的例子,我们给定90后用户的Bitmap,再给定一个全量用户的Bitmap。最终要求出的是存在于全量用户,但又不存在于90后用户的部分。

如何求出呢?我们可以使用异或操作,即相同位为0,不同位为1。

25769803776L = 11000000000000000000000000000000000B

8589947086L = 1000000000000000000011000011001110B

1.解析Word0,得知当前RLW横跨的空Word数量为0,后面有连续3个普通Word。

2.计算出当前RLW后方连续普通Word的最大ID是 64 X (0 + 3) -1 = 191。

3. 由于 191 < 400003,所以新ID必然在下一个RLW(Word4)之后。

4.解析Word4,得知当前RLW横跨的空Word数量为6247,后面有连续1个普通Word。

5.计算出当前RLW(Word4)后方连续普通Word的最大ID是191 + (6247 + 1)X64 = 400063。

6.由于400003 < 400063,因此新ID 400003的正确位置就在当前RLW(Word4)的后方普通Word,也就是Word5当中。

最终插入结果如下:

官方说明如下:

* Though you can set the bits in any order (e.g., set(100), set(10), set(1),* you will typically get better performance if you set the bits in increasing order (e.g., set(1), set(10), set(100)).* * Setting a bit that is larger than any of the current set bit* is a constant time operation. Setting a bit that is smaller than an * already set bit can require time proportional to the compressed* size of the bitmap, as the bitmap may need to be rewritten.

几点说明:

1. 该项目最初的技术选型并非Mysql,而是内存数据库hana。本文为了便于理解,把最初的存储方案写成了Mysq数据库。

1.文中介绍的Bitmap优化方法在一定程度上做了简化,源码中的逻辑要复杂得多。比如对于插入数据400003的定位,和实际步骤是有出入的。

2.如果同学们有兴趣,可以亲自去阅读源码,甚至是尝试实现自己的Bitmap算法。虽然要花不少时间,但这确实是一种很好的学习方法。

EWAHCompressedBitmap对应的maven依赖如下:
<dependency><groupId>com.googlecode.javaewah</groupId><artifactId>JavaEWAH</artifactId><version>1.1.0</version>
</dependency>

转载于:https://www.cnblogs.com/itplay/p/11089233.html

【算法】BitMap相关推荐

  1. 海量数据处理算法—Bit-Map

    1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空 ...

  2. 数据算法: Bitmap

    1. 初识 Bitmap Bitmap 也被称为位图.Bitmap 既是一种数据结构,又是一种图片类型.从数据结构的角度讲,Bitmap 适用于以下场景,后文会逐一进行阐述: 判重 定基 排序 压缩 ...

  3. 如何将数组中多个相同的数全部替换为另一个数_10亿数据如何快速找到某个数 | 经典算法BitMap详解...

    前言 BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射,怎么理解呢? 问题引入 有一个无序有界int数组{1,2,5,7},初步估计占用内存44=16字节,因为只有4个数 ...

  4. 位图算法BitMap

    位图算法的核心思想:用连续排列的内存字节bit位来代表连续的数据,用bit位的o和1状态来代表该数据是否出现.用内存空间来查找换取速度. 位图算法的主要用途:大量数据的查询场景 如图使用一个字节来表示 ...

  5. 【ARM 嵌入式 C 入门及渐进 4-- Linux 位图 bitmap】

    文章目录 1.1 位图算法-bitmap 1.1.1 bitmap 使用场景示例 1.1.2 bitmap算法实现 1.1 位图算法-bitmap 位图算法,是指使用一个 bit 位来表示数据状态. ...

  6. 数据结构与算法学习笔记15:最大流问题 / 二分图 / 有权无权二分图的匹配 / 匈牙利算法 / 银行家算法 / 稳定婚配

    数据结构与算法学习笔记15:最大流问题 / 二分图 / 有权无权二分图的匹配 / 匈牙利算法 / 银行家算法 / 稳定婚配 引入小题:最短路径 最大流问题(maximum flow problem) ...

  7. 计算机科学精彩帖子收集

    linux源码 LXR 源自"the Linux Cross Referencer",中间的"X"形象地代表了"Cross".与 Sourc ...

  8. 【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩 | JPEG 格式压缩 | WEBP 格式压缩 | 动态权限申请 | Android10 存储策略 )

    文章目录 一. 图片质量压缩 二. 图片尺寸压缩 三. Android 10 文件访问 四. 完整源码示例 上一篇博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供 ...

  9. 去重 指定区域数据_大数据分析常用去重算法分析

    去重分析在企业日常分析中的使用频率非常高,如何在大数据场景下快速地进行去重分析一直是一大难点.在近期的 Apache Kylin 沙龙上, Kyligence 大数据研发工程师陶加涛为大家揭开了大数据 ...

  10. Android阿面试积累,android项目开发实战密码

    公差为1的等差数列求和,如何优化 自己的优势在哪里 注解如何获取,反射为何耗性能? Java的GC机制,分代回收策略 Binder机制:ServiceManager什么时候注册的? int,long的 ...

最新文章

  1. [THUPC2019]不等式/[51Nod1598]方程最小值
  2. 内存位置访问无效_万字长文——java内存模型之volatile深入解读
  3. 第六章:Java_异常处理
  4. Redis持久化的几种方式——深入解析RDB
  5. android线程优先级大小,android 设置线程优先级 两种方式
  6. 隐藏虚拟键盘,解决键盘挡住UITextField问题
  7. 改善代码设计 —— 优化物件之间的特性(Moving Features Between Objects)
  8. 方便好用的在线CPU性能调优工具--perf的常见用法
  9. 深度学习中的梯度下降算法
  10. [2018.12.6]左偏树
  11. UBUNTU配置samba
  12. 解决拼音汉字混合搜索,由于同音字导致搜出不相干的内容
  13. 敏捷开发之利刃—db4o
  14. 集团申请选择企业邮箱注意事项
  15. Wifi攻击工具 3:图形化工具 fern-wifi-cracker
  16. 转行学什么就业前景好
  17. ROS示例----TIAGo教程
  18. 视频教程-使用Objective-C进行iOS移动开发-iOS
  19. 机智云OTA实践教程
  20. python中notebook的快捷键_现在就飞起来!Jupyter Notebook 那些如有神助的快捷操作...

热门文章

  1. 动态调用Web Service
  2. [北航软工]第一次团队作业
  3. Docker与CI持续集成/CD(转)
  4. 如何使用JDBC调用存储在数据库中的函数或存储过程 */
  5. QT如何设置应用程序的图标
  6. .NET开发者必备的工具箱
  7. HTML5 Canvas 自定义笔刷
  8. WEB框架研究笔记六(Spring WEB)
  9. 不可多得的Javascript(AJAX)开发工具 - Aptana
  10. RabbitMQ 相关概念