所謂的基數計數就是統計一組元素中不重復的元素的個數。如統計某個網站的UV,或者用戶搜索網站的關鍵詞數量;再如對一個網站分別統計了三天的UV,現在需要知道這三天的UV總量是多少,怎么融合多個統計值。
1、方法
(假設元素個數為m,去重后個數為n)
1、集合操作去重
時間復雜為O(m2),空間復雜度隨元素個數線性增長。數據量一大就崩了。
2、B+樹
將數據插入到B+樹中達到去重目的,然后順序訪問葉節點鏈從而得到n值。時間復雜的為O( lgm + n ),內存亦隨元素個數線性增長。數據量一大就崩了。
3、BitMap
用位數組來表示各元素是否出現,每個元素對應一位,所需的總內存為n bit。能大大減少內存占用且位操作迅速。
如果要統計1億個數據的基數值,大約需要內存100000000/8/1024/1024 ≈ 12M,內存減少占用的效果顯著。然而統計一個對象的基數值需要12M,如果統計10000個對象,就需要將近120G,同樣不能廣泛用於大數據場景。
4、概率算法
實際上目前還沒有發現更好的在大數據場景中准確計算基數的高效算法,因此在不追求絕對准確的情況下,使用概率算法算是一個不錯的解決方案。概率算法不直接存儲數據集合本身,通過一定的概率統計方法預估基數值,這種方法可以大大節省內存,同時保證誤差控制在一定范圍內。
目前用於基數計數的概率算法包括:
- Linear Counting(LC):早期的基數估計算法,LC在空間復雜度方面並不算優秀,實際上LC的空間復雜度與上文中簡單bitmap方法是一樣的(但是有個常數項級別的降低),都是O(Nmax);
- LogLog Counting(LLC):LogLog Counting相比於LC更加節省內存,空間復雜度只有O(log2(log2(Nmax)));
- HyperLogLog Counting(HLL):HyperLogLog Counting是基於LLC的優化和改進,在同樣空間復雜度情況下,能夠比LLC的基數估計誤差更小。
2、HyperLogLog
原理:

