EWAHCompressedBitmap資料結構及原理
本文基於Java版專案javaewah。
首先
首先要知道,EWAHCompressedBitmap是完全基於行程壓縮演算法壓縮的。
結構就是這樣,看起來很簡單。
在構造EWAHCompressedBitmap時,內部會初始化一個RunningLengthWord,來儲存EWAH壓縮演算法必需的兩個資料結構:
/**
* The array of words.
*/
final Buffer buffer;
/**
* The position in array.
*/
int position;
其中Buffer根據實現的不同可能是
- LongArray,內部為
long[]
,使用預設構造方法構造Bitmap時就會構造LongArray - LongBufferWrapper, 內部為
java.nio.LongBuffer
,這樣可以直接使用NIO的特性。在使用java.nio.ByteBuffer
構造Bitmap時會構造LongBufferWrapper
不管什麼實現,我們把Buffer直接理解為儲存了一堆long
的陣列即可。
RunningLengthWord
RunningLengthWord儲存了EWAHCompressedBitmap的全部資料,是整個專案中的核心。
其原理為:
將整個(未經過任何壓縮的)bitmap每64位拆分為一個最小單元(long
- 64位全都是相同的位元,要麼全都是1,要麼全都是0,這樣的資料可以被run-length壓縮。尤其是當這種情況發生在連續的多個long上的時候,壓縮效果更為明顯。
- 64位範圍內既有0又有1,這樣的資料不進行壓縮,而是直接儲存字面量,這樣的資料在論文中叫做Dirty Word,生動形象。其實如果整個bitmap中大量出現Dirty Word的話,壓縮效果會大打折扣。
根據上面的原理,RunningLengthWord使用了這樣的實現:
如果所示,在初始化時,Buffer中下標為0的位置一定是一個run-length,其64位被拆分成了三部分:
- 最低位(Running Bit
- 中間32位(Running Length): 表示當前的run-length壓縮了幾個64位(
long
)的連續相同bit。如果這個部分值為0,那麼最低位的取值沒有實際意義。 - 高31位(Number of Literal Words ):表示當前run-length後面緊接著未壓縮的字面量(Dirty Words)的數量。
如果Buffer中下標為N
的位置為run-length,且其高位31位表示的Number of Literal Words為2,則Buffer中下標為N+1
和N+2
的兩個位置一定是字面量。
另外有一個性能相關的措施,就是設定一個position
,始終指向整個Buffer中最後一個run-length,避免始終從頭開始定址。
舉個栗子
先插入9
因為要插入9,導致[0, 63]
範圍變成了Dirty Word,需要儲存為字面量,因此會發生下面這些步驟:
- 將Buffer中第0個run-length的高位Number of Literal Words部分改為1,表示後面的一個
long
為字面量; - 在Buffer中下標為1的位置插入一個表示字面量的
long
,表示[0, 63]
範圍的值。因為插入了9,所以第9位的位置需要設為1(最低位為第0位)。
再插入666
再插入666的話,如果不壓縮,那麼將會形成這樣的陣列:
[640, 703]:Dirty Word,包含值666
[576, 639]:全0
[512, 575]:全0
[448, 511]:全0
[384, 447]:全0
[320, 383]:全0
[256, 319]:全0
[192, 255]:全0
[128, 191]:全0
[ 64, 127]:全0
[ 0, 63]:Dirty Word,包含值9
可以看到,除了[0, 63]
和[640, 703]
兩個Dirty Word,中間的9個long
全都是0,是可以進行run-length壓縮的。步驟如下:
- 在Buffer中下標為2的位置插入一個run-length,其中Running Bit為0(壓縮的是0),Running Length為9(壓縮了9×64位),Number of Literal Words為1(後面有一個Dirty Word);
- 將
position
指向2,保持始終指向最後一個run-length; - 在Buffer中下標為3的位置插入一個字面量,表示
[640, 703]
,其中第26位為1,表示插入了值666。 - 目前Buffer已滿,將陣列大小由4擴充套件為8,以備後用。
run-length和字面量的轉換
對於一個字面量
字面量代表的64位範圍內既有0又有1,如果經過某些操作後,恰好所有0都變成了1,或者所有的1都變成了0,那麼這個字面量就會被轉換為run-length。
需要進行以下操作:
- 因為自己不再是字面量了,所以需要減少前一個run-length的Number of Literal Words的值。
- 檢查前後相鄰的
long
是不是run-length,如果是的話能不能與自己合併。如果合併的話,合併後當前位置將會變成空位,需要將後面的資料整體前移。 - 如果轉換後自己變成最後一個run-length,需要將position指向自己。
對於一個run-length
run-length代表了至少一個、多則成百上千個64位區間全都是相同的bit。如果某些操作導致其中出現一個異常值,將會切斷當前run-length,插入至少一個字面量。
需要進行以下操作:
- 如果異常值出現在run-length的前64位或末尾64位,則需要收縮run-length的大小,在前面或後面插入一個字面量。
- 如果異常值出現在run-length的中間,則會將當前run-length切成兩個較短的run-length,中間插入一個字面量。
- 如果當前run-length只包含64位,則直接將當前run-length替換為一個字面量。
- 上述操作完成後,更新發生變動的字面量前面的Number of Literal Words值。
總結
- 儲存結構簡單,只有一個大大的
long[]
,在bitmap較大時對GC不太友好。 - 除了有一個
position
指向最後一個run-length,其他再沒有能幫助隨機訪問的措施了,這就意味著,基本上所有的對bitmap的隨機訪問全都要從頭開始過一遍,時間是線性的。不過,人家是完全的行程壓縮,說隨機訪問有點欺負人,這種bitmap本身就不適合隨機訪問,大家也不要這樣用。 - 總覺得壓縮差那麼點意思。。在極端情況下,壓縮率甚至是負的。比如,你每隔64插入一個值試試。。
其實我不應該先研究RoaringBitmap再來研究EWAH的,現在看起來怎麼都不如RoaringBitmap了。。
後面我會專門寫一篇來比較RoaringBitmap和EWAHCompressedBitmap的效能指標,用資料來說話。
相關推薦
EWAHCompressedBitmap資料結構及原理
本文基於Java版專案javaewah。 首先 首先要知道,EWAHCompressedBitmap是完全基於行程壓縮演算法壓縮的。 結構就是這樣,看起來很簡單。 在構造EWAHCompressedBitmap時,內部會初始化一個Runnin
MySQL索引背後的資料結構及原理
摘要 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避免混亂,本文將只關注於BTree索引,因為這是平常使用
圖解 Java 中的資料結構及原理,傻瓜也能看懂!
最近在整理資料結構方面的知識, 系統化看了下Java中常用資料結構, 突發奇想用動畫來繪製資料流轉過程。 主要基於jdk8, 可能會有些特性與jdk7之前不相同, 例如LinkedList LinkedHashMap中的雙向列表不再是迴環的。 HashMap中的單鏈表是尾插, 而不是頭插入等等, 後文
RoaringBitmap資料結構及原理
首先 每個RoaringBitmap(GitHub連結)中都包含一個RoaringArray,名字叫highLowContainer。 highLowContainer儲存了RoaringBitmap中的全部資料。 RoaringArray hig
JAVA常用資料結構及原理分析
java.util包中三個重要的介面及特點:List(列表)、Set(保證集合中元素唯一)、Map(維護多個key-value鍵值對,保證key唯一)。其不同子類的實現各有差異,如是否同步(執行緒安全)、是否有序。 常用類繼承樹: 以下結合原始碼講解常用類實現原理及相互之間
查詢資料結構及Mysql資料庫索引原理(B-/+Tree)
轉載:https://blog.csdn.net/u014800380/article/details/64441164 摘要: 本文內容主要來源於網際網路上主流文章,只是按照個人理解稍作整合,後面附有參考連結。 https://yq.aliyun.co
MySQL索引背後的資料結構及演算法原理
作者 張洋 | 釋出於 2011-10-18 MySQL 索引 B樹 優化 摘要 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型
MySQL索引的資料結構及演算法原理
原文連結:MySQL索引背後的資料結構及演算法原理 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避
MySQL索引背後的資料結構及BTree B+Tree演算法原理
摘要本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避免混亂,本文將只關注於BTree索引
MySQL索引背後的資料結構及演算法原理(employees例項)
摘要 http://blog.codinglabs.org/articles/theory-of-mysql-index.html 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援
轉:MySQL索引背後的資料結構及演算法原理
@rover這個是C++模板 --胡滿超 stack<Postion> path__;這個裡面 ”<> “符號是什麼意思?我在C++語言裡面沒見過呢? 初學者,大神勿噴。
MySQL索引資料結構及演算法原理學習筆記
1、預備知識 (1)儲存介質一般為主存和磁碟 (2)主存(RAM)支援隨機存取,磁碟定址需要定位【磁軌】和【扇區】,對應產生【尋道時間】和【旋轉時間】,因此磁碟的存取速度往往是主存的【幾百分之一】 (3)由於【區域性性原理】的歸納,以及磁碟IO非常耗時
【轉】MySQL索引背後的資料結構及演算法原理
摘要 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避免混亂,本文將只關注於BTree
原理:資料結構-索引 && 應用篇:MySQL索引背後的資料結構及演算法原理詳解
特點簡介: 索引檔案比資料檔案小,可以有效地裝載到記憶體。通過對記憶體索引檔案的查詢定位到記錄,然後通過一次磁碟物件讀取操作就可以獲取到需要搜尋的物件。 靜態索引結構和動態索引結構啥區別? 我認為靜態是指新節點的加入對原有的索引結構不會發生改變,比如:稠密索引直接把新節點
轉MySQL索引背後的資料結構及演算法原理
摘要 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避免混亂,本文將只關注
[轉]MySQL索引背後的資料結構及演算法原理
作者:張洋來源:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 摘要本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索
MySQL索引背後的資料結構及演算法原理----驚歎的深入
摘要 本文以MySQL資料庫為研究物件,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支援諸多儲存引擎,而各種儲存引擎對索引的支援也各不相同,因此MySQL資料庫支援多種索引型別,如BTree索引,雜湊索引,全文索引等等。為了避免混亂,本文將只
MySQL索引背後的資料結構及演算法原理(七)
索引選擇性與字首索引既然索引可以加快查詢速度,那麼是不是隻要是查詢語句需要,就建上索引?答案是否定的。因為索引雖然加快了查詢速度,但索引也是有代價的:索引檔案本身要消耗儲存空間,同時索引會加重插入、刪除和修改記錄時的負擔,另外,MySQL在執行時也要消耗資源維護索引,因此索引
TrieTree字典樹資料結構的原理、實現及應用
一、基本知識 字典樹(TrieTree),又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計和排序大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是:最大限度地減少無謂的字串比較,查詢效率比雜湊表高。
使用R語言ggplot2包繪製pathway富集分析氣泡圖(Bubble圖):資料結構及程式碼
氣泡圖是在笛卡爾座標系同加入大小的引數所形成的可以表示三個變數關係的圖例。在對基因完成GO/KEGG分析後,使用氣泡圖可以直觀的展示pathway、pvalue、count之間的關係。下面為使用R語言ggplot2包繪製氣泡圖所需的資料結構及程式碼: 由於筆者常使用read.csv讀取