漫畫:什麼是Bitmap算法?









兩個月以前——java













爲知足用戶標籤的統計需求,小灰利用Mysql設計了以下的表結構,每個維度的標籤都對應着Mysql表的一列:程序員



要想統計全部90後的程序員該怎麼作呢?算法


用一條求交集的SQL語句便可:
sql


Select count(distinct Name) as 用戶數 from table whare age = '90後' and Occupation = '程序員' ;
數據庫



要想統計全部使用蘋果手機或者00後的用戶總合該怎麼作?bash


用一條求並集的SQL語句便可:
maven


Select count(distinct Name) as 用戶數 from table whare Phone = '蘋果' or age = '00後' ;學習





兩個月以後——優化












———————————————ui













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>複製代碼



—————END—————



喜歡本文的朋友們,歡迎長按下圖關注訂閱號程序員小灰,收看更多精彩內容

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息