【算法】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>
相關文章
相關標籤/搜索