【算法】BitMap

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

需求:

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

「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


两个月以前——java


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


要想统计全部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后' ;算法


「天天一算法」Bitmap算法


两个月以后——sql


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


———————————————数据库


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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

Bitmap不只方便查询,还能够去除掉重复的整型数。


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


一周以后......


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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


「天天一算法」Bitmap算法


如何求出呢?咱们可使用异或操做,即相同位为0,不一样位为1。


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


25769803776L = 11000000000000000000000000000000000B

8589947086L = 1000000000000000000011000011001110B


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


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当中。

最终插入结果以下:


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


「天天一算法」Bitmap算法


官方说明以下:

* 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.

「天天一算法」Bitmap算法


几点说明:

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>
相关文章
相关标签/搜索