首先
每個roaringbitmap(github鏈結)中都包含乙個roaringarray,名字叫highlowcontainer。
highlowcontainer儲存了roaringbitmap中的全部資料。
roaringarray highlowcontainer;
這個名字意味著,會將32位的整形(int)拆分成高16位和低16位兩部分(兩個short)來處理。
roaringarray的資料結構很簡單,核心為以下三個成員:
short keys;
container values;
int size;
每個32位的整形,高16位會被作為key儲存到short keys中,低16位則被看做value,儲存到container values中的某個container中。keys和values通過下標一一對應。size則標示了當前包含的key-value pair的數量,即keys和values中有效資料的數量。
keys陣列永遠保持有序,方便二分查詢。
下面介紹到的是roaringbitmap的核心,三種container。
通過上面的介紹我們知道,每個32位整形的高16位已經作為key儲存在roaringarray中了,那麼container只需要處理低16位的資料。
arraycontainer
static final int default_max_size = 4096
short content;
結構很簡單,只有乙個short content,將16位value直接儲存。
short content始終保持有序,方便使用二分查詢,且不會儲存重複數值。
因為這種container儲存資料沒有任何壓縮,因此只適合儲存少量資料。
arraycontainer占用的空間大小與儲存的資料量為線性關係,每個short為2位元組,因此儲存了n個資料的arraycontainer占用空間大致為2n位元組。儲存乙個資料占用2位元組,儲存4096個資料占用8kb。
根據原始碼可以看出,常量default_max_size值為4096,當容量超過這個值的時候會將當前container替換為bitmapcontainer。
final long bitmap;
這種container使用long儲存位圖資料。我們知道,每個container處理16位整形的資料,也就是0~65535,因此根據點陣圖的原理,需要65536個位元來儲存資料,每個位元位用1來表示有,0來表示無。每個long有64位,因此需要1024個long來提供65536個位元。
因此,每個bitmapcontainer在構建時就會初始化長度為1024的long。這就意味著,不管乙個bitmapcontainer中只儲存了1個資料還是儲存了65536個資料,占用的空間都是同樣的8kb。
private short valueslength;
int nbrruns = 0;
runcontainer中的run指的是行程長度壓縮演算法(run length encoding),對連續資料有比較好的壓縮效果。
它的原理是,對於連續出現的數字,只記錄初始數字和後續數量。即:
對於數列11,它會壓縮為11,0;
對於數列11,12,13,14,15,它會壓縮為11,4;
對於數列11,12,13,14,15,21,22,它會壓縮為11,4,21,1;
原始碼中的short valueslength中儲存的就是壓縮後的資料。
這種壓縮演算法的效能和資料的連續性(緊湊性)關係極為密切,對於連續的100個short,它能從200位元組壓縮為4位元組,但對於完全不連續的100個short,編碼完之後反而會從200位元組變為400位元組。
如果要分析runcontainer的容量,我們可以做下面兩種極端的假設:
最好情況,即只存在乙個資料或只存在一串連續數字,那麼只會儲存2個short,占用4位元組
最壞情況,0~65535的範圍內填充所有的奇數字(或所有偶數字),需要儲存65536個short,128kb
只有bitmapcontainer可根據下標直接定址,複雜度為o(1),arraycontainer和runcontainer都需要二分查詢,複雜度o(log n)
這是我畫的一張圖,大致描繪了各container占用空間隨資料量的趨勢。其中,
arraycontainer一直線性增長,在達到4096後就完全比不上bitmapcontainer了
bitmapcontainer是一條橫線,始終占用8kb
runcontainer比較奇葩,因為和資料的連續性關係太大,因此只能畫出乙個上下限範圍。不管資料量多少,下限始終是4位元組;上限在最極端的情況下可以達到128kb。
建立時:
建立包含單個值的container時,選用arraycontainer
建立包含一串連續值的container時,比較arraycontainer和runcontainer,選取空間占用較少的
轉換:
針對arraycontainer:
如果插入值後容量超過4096,則自動轉換為bitmapcontainer。因此正常使用的情況下不會出現容量超過4096的arraycontainer。
呼叫runoptimize()方法時,會比較和runcontainer的空間占用大小,選擇是否轉換為runcontainer。
針對bitmapcontainer:
如果刪除某值後容量低至4096,則會自動轉換為arraycontainer。因此正常使用的情況下不會出現容量小於4096的bitmapcontainer。
呼叫runoptimize()方法時,會比較和runcontainer的空間占用大小,選擇是否轉換為runcontainer。
針對runcontainer:
只有在呼叫runoptimize()方法才會發生轉換,會分別和arraycontainer、bitmapcontainer比較空間占用大小,然後選擇是否轉換。
RoaringBitmap資料結構及原理
每個roaringbitmap github鏈結 中都包含乙個roaringarray,名字叫highlowcontainer。highlowcontainer儲存了roaringbitmap中的全部資料。roaringarray highlowcontainer 這個名字意味著,會將32位的整形 ...
RoaringBitmap原理和應用
設計思路 我們以存放 integer 值的 bitmap 來舉例 存放long型別的儲存方式會有所不同 rbm 把乙個 32 位的 integer 劃分為高16 位和低16 位,通過高16位找到該資料儲存在哪個桶中 高 16 位可以劃分 2 16 個桶 把剩餘的低 16 位放入該桶對應的 conta...
資料探勘 資料
對關注的屬性,樣本與原始資料集有相同的性質,則用抽樣計算的結果與全集是一樣。1.1 抽樣的方法 1 簡單隨機抽樣 random sampling 放回 不放回 2 分層抽樣 stratified sampling 如果資料集不同型別的資料數量差異過大,則隨機抽樣會丟失數量少的樣本。可針對不同資料組,...