【UV統計】海量數據統計的前世今生


轉載請注明出處

背景

在互聯網公司中,每個項目都需要數據統計、分析,便於項目組利用詳細數據研究項目的整體情況,進行下一步的調整。在數據統計中,UV統計是最常見的,也是最普遍的。有的場景要求實時性很高,有點場景要求准確性很高,有的場景比較在意計算過程中的內存。不同的場景使用不同的算法,下面我們從0到1簡單介紹下UV統計領域。

什么是UV統計

假設我們的場景是商家這邊上架一系列水果,然后需要統計出一共上架幾種水果。具體如下所示:

針對這個問題,我們想到的最簡單的方式就是利用STL中的set處理。

SET

上架一個水果的時候,也同時在set中插入。最后需要統計的時候,直接計算set中一共有幾個水果即可。具體如下所示:

這種方式准確率是絕對准確的,但是這種方式耗費的內存是很大的。
假設每個水果需要 K 字節,那么如果有 M 個水果,一共需要 K * M 字節。那么我們能不能縮小這里的內存呢?
稍微損失一點准確率換取內存?具體見下面HashMap的方式

HASHMAP

這種算法在上架一個水果的時候,只需要在特定的位置置1即可,而不需要存儲這個位置上究竟是何種水果。然后在統計的時候,只需要統計hashmap里面有多少個1即可。具體如下所示:
具體如下所示:

那么如果有M個水果,這里其實只需要 M / 8 字節,相比set的方式內存直接縮小到1/8。當然Hash肯定會有沖突的,所以這里肯定有一定准確率的損失。
但是如果涉及到海量數據的UV統計,這里的內存還是很大的。
能否用上統計學進一步縮小內存呢?具體見下面的Linear Count的方式。

Linear Count

這種算法在上架一個水果的時候,完全跟hashmap一致,在相應位置置1。
然后在統計的時候,利用統計學的方式,根據hashmap中零的個數給出一個估算值。具體如下所示:

假設M為哈希桶長度,那么每次上架水果,每個桶被選中的概率為:

\[\frac{1}{M} \]

然后在上架N個元素后,某個桶為0的概率為:

\[(1-\frac{1}{M}) ^N \]

所以在上架n個元素后,哈希桶中零的個數期望為:

\[ZeroNum=\sum_{i=1}^M (1-\frac{1}{M}) ^N = M (1-\frac{1}{M}) ^N= M ((1+\frac{1}{-M})^{-M})^{-\frac{N}{M}}) \approx Me^{- \frac{N}{M}} \]

所以最終:

\[N = UV = -M ln(\frac{ZeroNum}{M}) \]

所以Linear Count算法中,只需統計下hashmap中零的個數,然后代入上式即可。
這種算法在N很小的時候,准確率是很高的,但是N很大的時候,它的准確率急劇下降。
針對海量數據的情況,LogLog Count的算法更加魯棒

LogLog Count

這種算法跟上面幾種都不同,上架水果的時候,在相應桶里面記錄的是二進制數后面最長的連續零個數。然后統計的時候,利用統計學的方式,根據存儲中最長連續后綴零個數,得出一個估計值。具體如下所示:

它的原理如下:

這里如果只使用一個桶來估計的話,它的誤差是很大,需要用分桶平均的方式來減少它的誤差。

分桶平均

既然這里利用了分桶來減少誤差,那么這里統計的時候就必須合起來,這里有4種方式:

  • 算術平均:$$UV=\frac{\sum_{j=1}^mUV_j} { m}$$
  • 幾何平均:$$UV=\sqrt[m]{UV_1...UVm}$$
  • 調和平均:$$UV=\frac{m}{\sum_{j=1}mUV_j{-1}}$$
  • 中位數:$$UV=mediam {UV_1,...,UV_m}$$

LogLog Count利用的是算術平均的方式,所以最終估計值為:

\[UV=2^{\frac{\sum_{j=1}^m{UV_j}}{m}} \]

這種算法對於基數大的情況下准確率挺高的,但是基數小的情況下准確率很低。

HyperLogLog Count

這種算法跟LogLog Count 類似,有個區別點就是它在求均值的時候利用了調和平均數,而不是算術平均數。這里最終估計值為:

\[UV=mm(\sum_{j=1}^m{2^{-M_j}})^{-1} \]

然后它還引入了分段誤差修正。

誤差修正

具體可以看我github上的代碼:HyperLogLog

總結

准確率 內存 耗時
Set 絕對准確 K * M O(Mlog(M))
HashMap 很高 M/8 O(M)
Linear Count 基數小高,基數大低 M/8 O(M/8)
LogLog Count 基數小低,基數大高
HyperLogLog Count


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM