HyperLogLog:海量資料下的基數計算
1. 什麼是基數計算
基數計算(cardinality counting)指的是統計一批資料中的不重複元素的個數,常見於計算獨立使用者數(UV)、維度的獨立取值數等等。實現基數統計最直接的方法,就是採用集合(Set)這種資料結構,當一個元素從未出現過時,便在集合中增加一個元素;如果出現過,那麼集合仍保持不變。
在大資料的場景中,實現基數統計往往去面臨以下的兩個問題:
- 如果有效的儲存原始資料,以避免資料佔用空間過多,這裡就涉及到儲存空間壓縮的問題
- 如果能夠跨不同的維度、不同的時間段實現基數計算,比如在計算日度UV的情況下,如果計算出周度、或者月度的UV
本文旨在介紹目前比較成熟的基數計算的方式,並通過例項對比他們在解決以上兩個問題上的效果,最後引出本文的重點,HyperLogLog演算法的實現和應用。
2. Bitmap
2.1 基本原理
Bitmap進行基數計算的方法,是先定義一個bit陣列,陣列中的每一位對應資料的一種取值。由於bit是計算機中的最小單位,使用bit可以大量的減少儲存空間。例如一個陣列[1,3,4,5],那麼對應的bitmap即為[0,0,0,1,1,1,0,1],後續每新增加一個元素,就和現有的bitmap進行OR操作,通過計算bitmap中1的個數,即可以得到基數計算的結果。
正是因為bitmap之間對OR也是良好支援的,兩個bitmap在進行OR操作之後,便是這兩個條件組合下的基數計算結果,因此使用bitmap是可以實現任意條件下的基數計算。
2.2 空間使用
按照上面介紹的原理,進行bitmap的構建。假如統計1億資料的基數值,大約需要記憶體100000000/8/1024/1024 ~= 12M,如果有100個這樣的物件,就需要1.2G的記憶體空間,可見佔用記憶體還是很大的,在實際業務中基本很少使用。
3. Linear Counting
3.1 基本原理
Linear Counting是採用概率的方式進行基數估計的最簡單的方法。下面通過一個例項描述Linear Counting的計算過程:
- 資料雜湊:假設原始資料的基數為n,使用一組雜湊空間為m的雜湊函式H,將原始資料轉換為滿足均勻分組的一組雜湊陣列。
-
分桶資料統計:構建一個長度為m的bitmap,其中每一個bit對應雜湊空間的一個值。生成雜湊陣列的值如果存在,則把相應的bit設定為1。當所有值設定完成後,統計bitmap中為0的bit數為u。
可以通過下述的公式計算基數估計的結果:
注意這裡的log指的是自然對數。
公式的推導過程有興趣的可以參考這篇文章。其中最重要的是要清楚,在經過n次資料的雜湊後,bitmap中的某個bit值為0,是一個伯努利事件。記住這一點再理解公式推導就容易多了。
3.2 空間使用
Linear Counting的空間使用,和bitmap相比,空間複雜度是一致的,僅有線性下降。因此如果對於1億的原始資料,仍然需要MB級別的記憶體空間儲存。Linear Counting在實際應用中也很少被使用。
4. LogLog Counting
4.1 伯努利過程
在介紹LogLog Counting之前,我們先來回顧一下伯努利過程的概念。
伯努利過程是一個由有限個或無限個的獨立隨機變數 X1, X2, X3 ,..., 所組成的離散時間隨機過程,其中 X1, X2, X3 ,..., 滿足如下條件:
對每個 i, Xi 等於 0 或 1; 對每個 i, Xi = 1 的概率等於 p. 換言之,伯努利過程是一列獨立同分布的伯努利試驗。每個Xi 的2個結果也被稱為“成功”或“失敗”。所以當用數字 0 或 1 來表示的時候,這個數字被稱為第i個試驗的成功次數。
舉一個常見的例子:每次拋硬幣之後,出現正面和反面的概率分別為1/2,如果不停地拋硬幣,直至出現正面為止,這就是一個伯努利過程。
這樣,我們假設一共進行了n次伯努利過程,出現正面的次數分別為k1, k2, ... kmax,那麼有以下兩個結論:
- n次伯努利過程的投擲次數都不大於kmax
- n次伯努利過程,至少有一次的投擲次數等於kmax
已知投擲k次才出現正面的概率為:1/2^k,那麼:
-
第一種情況的概率為:
-
第二種情況的概率為:
如果n >> 2^k,則P(x >= kmax)為0;如果n << 2^k,則P(x <= kmax)為0。因此我們可以用2^k來作為n的近似估計結果。
4.2 伯努利過程與LogLog Counting
如何將基數計算,等價地認為是一個伯努利過程,是LogLog Counting的關鍵所在。這裡我們可以把原始資料進行雜湊,雜湊後的陣列是滿足均勻分佈的。把每個元素看做一個投擲硬幣的過程,將元素轉換為2進位制之後,每個bit出現0和1的概率是相等的。從高位開始查,第一次出現1的位置記為k,即等同於投擲硬幣時出現第一個正面,將所有元素出現1的位置的最大值,記為kmax,那麼2^kmax就是基數計算的結果。
4.3 LogLog Counting計算過程
- 資料雜湊:這個和Linear Counting是類似的,都需要保證雜湊後的資料是滿足均勻分佈的。
- 轉換為2進位制:將雜湊後的每個元素,都轉換為2進位制,由於資料在雜湊後滿足均勻分佈的,2進位制資料每一個bit的0和1出現的概率都是1/2,這裡設2進位制資料的位數為L。
- 統計第一個1出現的位置:分別計算每個2進位制資料,第一次出現1的次數。所有次數中的最大值為kmax,那麼2^kmax就是最終結果。
下圖中給出一個針對一個元素進行k值計算的過程。
4.4 資料分桶
上面的計算過程,由於是單一估計量,可能會出現一定的偶然性導致誤差。因此這裡引入資料分桶的方法。取雜湊空間分成m個桶,用雜湊值的前幾個bit的值來決定資料屬於哪一個桶,再對桶內的資料取k值,最終計算出kmax。再將所有桶的kmax取平均數,這樣就通過多次估計取平均的方式,消除了單一估計可能存在的偶然性誤差。計算公式如下:
4.5 誤差修正和分析
以上的過程仍然是存在誤差的,並不是無偏估計。將上述過程修正為無偏估計的過程由於過於複雜,這裡就不再介紹了。需要了解的是,最終結果的誤差公式為:
4.6 空間使用
到這裡,我們就可以理解LogLog Counting中兩個log了,它們的含義分別如下:
- 第一次log,和Linear Counting很類似,由於使用雜湊,壓縮了資料空間。
- 第二次log,由於在儲存雜湊值的第一次1出現的次數時,只需要儲存結果k,而不需要儲存原始的雜湊值,進一步節省了空間。
加入雜湊之後的值有32bit,那麼每個桶需要5bit儲存kmax的值,m個桶就是m5/8 B。
如果基數是1億個(227),當分桶數為1024時,每個桶的基數上限為227 / 2^10 = 217,log(log(217))=4.09,那麼每個桶需要5bit儲存kmax,總共需要的空間為51024/8,等於640B,可見是非常小的。
5. Adapative Counting
通過概率計算可知,LogLog Counting由於使用了幾何平均值,可能出現在基數較小的情況,有些桶是為空的。空桶對於最後平均值的計算干擾較大。
Adapative Counting的思想是將Linear Counting和LogLog Counting進行結合。Linear Counting和LogLog Counting的儲存結構是類似的,僅僅是Linear Couting關心桶是否為空,而LogLog Counting需要桶中的kmax。
最終分析得到的結論是:在空桶率大於0.051時,使用Linear Counting的偏差率更小;在空桶率小於0.051時,使用LogLog Counting的偏差率更小。
6. HyperLogLog Counting
HyperLogLog Counting,是在LogLog Counting的基礎上,將桶之間計算採用的幾何平均,修改為調和平均,可以有效的減少空桶對於平均值的影響。
調和平均的計算公式如下:
使用調和平均後的偏差公式為:
可見偏差期望和LogLog Counting相比要更小。
參考文獻
相關文章
- 【UV統計】海量資料統計的前世今生
- 初識Redis的資料型別HyperLogLogRedis資料型別
- 得物新一代可觀測性架構:海量資料下的存算分離設計與實踐架構
- 海量資料架構下如何保證Mycat的高可用?架構
- (資料科學學習手札88)基於geopandas的空間資料分析——空間計算篇(下)資料科學
- ☕【難點攻克技術系列】「海量資料計算系列」如何使用BitMap在海量資料中對相應的進行去重、查詢和排序排序
- 基於TableStore的海量電商訂單後設資料管理
- 海量資料處理
- Redis 集合統計(HyperLogLog)Redis
- 計組之資料運算:9、浮點數的表示
- 計算資料庫中所有表的記錄條數資料庫
- 大資料計算生態之資料計算(二)大資料
- 大資料計算生態之資料計算(一)大資料
- 海量資料的併發處理
- 尋找海量資料集用於大資料開發實戰(維基百科網站統計資料)大資料網站
- 計算機資料的表示計算機
- 【計算機基礎】我講大致講清了資料的表示計算機
- Java程式設計基礎03——進位制運算&資料型別&變數Java程式設計資料型別變數
- Redis 三種特殊資料型別之 HyperloglogRedis資料型別
- Redis中 HyperLogLog資料型別使用總結Redis資料型別
- ICLR 2020 Oral | 基於計算約束下的有用資訊的資訊理論ICLR
- 在 MySQL 中,如何計算一組資料的中位數?MySql
- [例項]計算所輸入資料的所有公約數
- 海量資料處理2
- 強烈推薦|海量計算機程式設計相關電子書免費下載計算機程式設計
- 海量資料的分頁怎麼破?
- 資料處理02:Python數值計算包NumPyPython
- 大資料計算的基石——MapReduce大資料
- 開源模式下的雲端計算和大資料現狀模式大資料
- HyperLogLog
- 微信後臺基於時間序的海量資料冷熱分級架構設計實踐架構
- 杉巖資料:海量智慧儲存,打造新基建數字底座
- 計算機計算小數除法的陷阱計算機
- Redis Hyperloglog的原理及數學理論的通俗理解Redis
- 大資料環境下計算機軟體技術分析大資料計算機
- 漫談OB | OceanBase 在海量資料和高併發下的應用實踐
- 分散式架構馭數而行,海量資料方能有備無患分散式架構
- 巨量算數:2022抖音熱點資料包告(附下載)