基數是指一個集合中,不同的數的個數。
基數統計是集合不同的數的個數。比如說一個集合{0, 1, 2, 2, 4, 5},其基數是5,而個數是6。因為1重復出現了兩次。基數是個去重統計。
基數估計是估計一個集合中不同的數的個數,不是數據總量的估計,也不是基數的精確計算。而是用概率算法的思想,來用低空間和時間成本,以一個很低的誤差度來估計數據的基數。
Flajolet–Martin algorithm
這是一個概率算法,把集合的數,通過hash算法,均勻(理論上盡量均勻)hash到一個區間

- 定義 y的二進制表示的第k位的值
)
所以:
2^k) - 定義:
=\min_{k>=0}bit(y,k)\ne0, \rho(0)=L) - 算法描述如下:
- Initialize a bit-vector BITMAP to be of length L and contain all 0's.
- For each element X in M:
; y =hash(x) )
=1 ) - Let R denote the smallest index i such that
=0 ) - Estimate the cardinality of M as

where 
算法思想:
- 假設集合M一共有n個數,當集合M的x,均勻hash到新的hash空間[0, 2^L], 則BIT(0)能被訪問n/2次。 因為最低bit位的0,1表示了奇偶數,均勻分布下,奇數大概有一半。所以有n/2的機會,使得BITMAP[0]=1, 同理 BITMAP[1]=1有n/4的機會
- 所以, 對于BITMAP[i] = 0的位置i,表示 n < 2^i, 所以算法中的R可以估計,n能使得BITMAP為1的位置的最高點。使得n約為2^R。 其中大約的系數和嚴格的證明,可以參考引用的論文。
[引用]
- Flajolet, Philippe; Martin, G. Nigel (1985). "Probabilistic counting algorithms for data base applications" (PDF). Journal of Computer and System Sciences. 31 (2): 182–209. doi:10.1016/0022-0000(85)90041-8.
LogLog algorithm
LogLog也是概率算法,使用m個bit位,使用的bit位m越大算法效果越好,具體算法過程如下:
- 與上面算法類似,需要把原始hash到一個數值空間M,即:

- 初始化m個存儲位為0, 即:
}= 0; 1 \le i \le m; \ m=2^k ) - 同樣定義:
=\min_{i>=0}bit(y,i)\ne0 \qquad [1]) - 對M中的每個x,


} := max \lbrack s^{(j)}, \rho(b{k+1}b_{k+2}\cdots) \rbrack ; ) - 計算基數估計,
}} )
算法思想:
- 在上面Flajolet–Martin算法的基礎上,進行改進。 將集合M的元素分散到m個桶,然后每個桶中的元素采用Flajolet–Martin一致的思路。
- 對于有n個不同元素的集合M,大約有n/2^k個不同元素,它們的rho值(LogLog算法中式子[1])等于k。當k=1的時候,也就是n/2個元素會有BITMAP[0]=1(見Flajolet–Martin算法)。所以,
 := \max_{x \in M}\rho(x) )
可以作為 的粗略估計。 - 使用元素x的前k個bit位的值,作為m個桶的桶序號,把x落入相應的桶中。這樣每個桶中的元素個數,大約是n/m
- 每個桶,采用2中描述的,可以對每個桶i的基數有估計出,有:
}) - 綜合3,4可以知道,每個桶基數的期望是 n/m,等于每個桶基數估計的均值
}) - 所以大致上,
}} )
根據更深入的分析推導,有
}} )
其中,
\frac{1-2^{1/m}}{log2} \rbrack ^{-m}; \Gamma(s)=\frac1s\int_{0}{\infty}e{-t}t^sdt)
來修正均值帶來的系統偏差 - 更詳細的推導和論證參考引用文章
[引用]
- Durand, Marianne; Flajolet, Philippe (2003). "Loglog Counting of Large Cardinalities" (PDF). Algorithms - ESA 2003. Lecture Notes in Computer Science. 2832. p. 605. doi:10.1007/978-3-540-39658-1_55. ISBN 978-3-540-20064-2.
HyperLogLog algorithm
HyperLogLog算法,在LogLog算法上做了改進,就是把m個桶的平均值,從LogLog的幾何平均數,改成了調和平均數.
在HyperLogLog的最終實現上,另外做了修正。對小、中、大范圍的值,分別做了修正。具體算法描述如下:(描述了[0,10^9]內的基數估計)

=\min_{i>=0}bit(y,i)\ne0 )
 \ for \ m \ge 128; )
Program HyperLogLog(input M: multiset of items from domain D):
- 
- },s{(2)},\cdots,s^{(m)}, to \ 0;)
- 


} := max \lbrack s^{(j)}, \rho(b{k+1}b_{k+2}\cdots) \rbrack ; ) - }} \rbrack ^{-1} )
- small range correction


 \ else \ set \ E^{}:=E; \ endif)

intermediate range - no correction

large range correction
; \ endif) - return

[引用]
- Flajolet, P.; Fusy, E.; Gandouet, O.; Meunier, F. (2007). "HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm" (PDF). AOFA ’07: Proceedings of the 2007 International Conference on the Analysis of Algorithms.
基數估計算法的比較
應用
基數估計的應用比較廣泛,對于存儲空間和實時要求比較高,但是精度要求能容忍一定誤差的時候,基數估計是個很好的選擇。
基數估計的應用舉例:
- HyperLogLog算法,在redis中也有應用。
- 基數估計應用在數據庫優化中,用來估計復雜查詢涉及的映射、連接等操作的數量。
- 路由器使用基數估計,在線實時的分析特定類型的事件,為防止Dos、port scan服務。
- 復雜的網絡拓撲結構中,用來估計連接結點對的數量