1. 程式人生 > >五種常用基數估計演算法效果實驗及實踐建議

五種常用基數估計演算法效果實驗及實踐建議

之前我曾寫過一系列關於基數估計(cardinality estimation)演算法的文章,文中介紹了一些常用基數估計演算法的原理。最近對常用的基數估計演算法做了一些實驗,這篇文章描述了實驗結果,包括這些演算法的估計效果及誤差狀況,主要通過圖表展示。通過觀察實驗資料和視覺化圖表可以加強對各種基數估計演算法理論分析的直觀理解。

文章首先會對實驗做一些說明,然後通過圖表詳細展示實驗資料,最後會根據實驗結果總結一些實踐中有用的結論。

實驗說明

演算法選擇

這次實驗共選擇了五種基數估計演算法,分別是:

  • Linear Counting1
  • LogLog Counting2
  • Adaptive Counting
    3
  • HyperLogLog Counting4
  • HyperLogLog++ Counting5

演算法實現使用我所在部門(阿里巴巴商家資料部)的開源基數估計演算法庫ccard-lib

資料準備

雜湊函式採用murmurhash32(HyperLogLog++採用murmurhash64)。

因實驗結果的可靠性僅與雜湊值的分佈均勻性有關,而根據之前相關研究murmurhash對於順序型資料具有良好的均勻性。因此為了簡化實驗,原始資料使用1-1,000,000無符號64bit整型的小端序表示

下面將通過實驗驗證原始資料雜湊後的均勻性。

實驗過程

  • 將原始資料經過murmurhash處理後,驗證分桶數在\(2^{10}\),\(2^{12}\)和\(2^{16}\)下資料的均勻性,即看各個桶的元素數量是否大致相等;同時驗證各個桶中元素二進位制表示的最長0字首是否服從冪率分佈。
  • 對五種基數估計演算法,分佈記錄\(2^{10}\),\(2^{12}\)和\(2^{16}\)三種分桶數量下從1到1,000,000的估計值和相對誤差值。取樣點為100的整倍數,因此共10,000個取樣點。
  • 比較在\(2^{10}\),\(2^{12}\)和\(2^{16}\)三種分桶數量下五種基數估計演算法的誤差走勢。

實驗

資料均勻性

下面首先驗證原始資料經過雜湊後基本服從均勻分佈,從而滿足各種基數估計演算法的基本前提條件。下面的結果通過murmurhash32雜湊值給出,實際中採用murmurhash64得到了基本一致的結論。

對於32bit雜湊值,分桶數為\(2^p\)時,用前\(p\)bit作為桶編號,剩下的\(32-p\)作為用於統計0字尾(因為均勻分佈的假設,統計0字尾和0字首是等效的,ccard-lib中除HyperLogLog++外採用統計0字尾的方式)的位元串。例如對於雜湊值“01001010111010100101000000100100”,分桶數為\(2^{10}\)時,其桶編號為“0100101011”,即十進位制的“555”,剩餘部分為“1010100101000000100100”,零字尾長度為2。

驗證分桶均勻性

下面通過柱狀圖分別給出\(2^{10}\),\(2^{12}\)和\(2^{16}\)三種分桶下各桶元素數量的分佈,在柱狀圖中bins的數量均為100,因此圖中每個bin並不對應一個桶。

murmurhash32雜湊值分佈(p=10)

murmurhash32雜湊值分佈(p=12)

murmurhash32雜湊值分佈(p=16)

可以看到,三種分桶下資料均基本服從均勻分佈。

0字尾長度的冪率分佈性

按照理論預言,如果雜湊均勻性足夠好,雜湊剩餘部分的關鍵統計量(最長0字尾長度)應該大約服從底數為2的冪率分佈。

下圖中橫座標表示0字尾長度,縱座標表示0字尾為此長度的雜湊值個數。

0字尾長度分佈(p=10)

0字尾長度分佈(p=12)

0字尾長度分佈(p=16)

可以看到在三種分桶下統計量分佈符合預期。

通過以上分析可知實驗資料滿足基數估計演算法關於均勻性的假設。

基數估計演算法效果

下面給出五種基數估計演算法的估計效果和誤差走勢。如未特殊說明,實驗分桶數均為\(2^{10}\),\(2^{12}\)和\(2^{16}\)。

Linear Counting

ccard-lib中當單獨使用Linear Counting時,採用bit為單位記錄雜湊結果。因此實際的精度為分桶數的8倍,例如\(2^{10}\)時,實際的精度為1024*8=8192。

估計效果

Linear Counting(p=10)

Linear Counting(p=12)

Linear Counting(p=16)

相對誤差

Linear Counting誤差(p=10)

Linear Counting誤差(p=12)

Linear Counting誤差(p=16)

結論

如理論預期,由於Linear Counting的有效性取決於bitmap中存在空位置,當有位置留空時,估計效果還不錯,但是當bitmap全滿後,Linear Counting完全失效。Linear Counting的有效估計範圍線性依賴於bitmap長度。

LogLog Counting

估計效果

LogLog Counting(p=10)

LogLog Counting(p=12)

LogLog Counting(p=16)

相對誤差

LogLog Counting誤差(p=10)

LogLog Counting誤差(p=12)

LogLog Counting誤差(p=16)

結論

LogLog Counting的表現基本與理論相符,可以看到當基數不太大的時候,LogLog Counting誤差非常大,這是因為LogLog Counting在基數較小的段存在一個很大的偏差。為了明確看到這個偏差,我們擷取前十分之一放大,也就是1-100,000這一段的效果圖:

LogLog Counting小基數區間(p=10)

LogLog Counting小基數區間(p=12)

LogLog Counting小基數區間(p=16)

可以很明顯的看到估計值嚴重偏離基準,而且分桶數越多這個偏差反而越明顯。

Adaptive Counting

估計效果

Adaptive Counting(p=10)

Adaptive Counting(p=12)

Adaptive Counting(p=16)

相對誤差

Adaptive Counting誤差(p=10)

Adaptive Counting誤差(p=12)

Adaptive Counting誤差(p=16)

結論

由於分別在基數較小和較大時使用Linear Counting和LogLog Counting,Adaptive Counting克服了兩者的缺陷,屬於比較穩定的基數估計方法。而且隨著分桶數的增加,估計的偏差和方差均明顯減小。

HyperLogLog Counting

估計效果

HyperLogLog Counting(p=10)

HyperLogLog Counting(p=12)

HyperLogLog Counting(p=16)

相對誤差

HyperLogLog Counting誤差(p=10)

HyperLogLog Counting誤差(p=12)

HyperLogLog Counting誤差(p=16)

結論

HyperLogLog Counting採用調和平均數取代LogLog Counting中的幾何平均數,旨在減小離群點的影響,並且對Linear Counting轉折閾值做了調整。從實驗效果看,在分桶數較小時,改進效果並不明顯,不過在\(2^{16}\)分桶下,整體偏差和穩定程度優於Adaptive Counting。

但是從誤差圖中可以看到,在200,000附近出現了一個明顯的脈衝。其原因在Google關於HyperLogLog++ Counting的論文中5有分析,其主要是因為在Linear Counting剛轉折後的一小段區域記憶體在一個偏差,HyperLogLog++ Counting的一個改進就是對這個區域的偏差進行了修正。

HyperLogLog++ Counting

估計效果

HyperLogLog++ Counting(p=10)

HyperLogLog++ Counting(p=12)

HyperLogLog++ Counting(p=16)

相對誤差

HyperLogLog++ Counting誤差(p=10)

HyperLogLog++ Counting誤差(p=12)

HyperLogLog++ Counting誤差(p=16)

結論

可以看到HyperLogLog++ Counting的效果非常令人失望,按論文中說法,HyperLogLog++ Counting應該比HyperLogLog Counting更準確,但實際效果不但整體偏差和方差變大,而且偏差修正的閾值明顯有問題,導致一個非常明顯的誤差脈衝。

究其原因,個人認為HyperLogLog++ Counting中的偏差修正和轉折閾值均是通過統計方法給出,並不是數學上的解析結果,因此對於不同的資料、不同的雜湊可能並不通用。

誤差比較

為了更清楚對比五種演算法的誤差情況,下面給出五種演算法的誤差曲線疊加圖,仍然是採用三個分桶數。

誤差對比(p=10)

誤差對比(p=12)

誤差對比(p=16)

實踐建議

下面根據實驗結果從個人角度給出一些基數估計演算法的實踐性建議,當然只代表個人意見,不同人對實驗結果可能有不同解讀。

  • Linear Counting和LogLog Counting由於分別在基數較大和基數較小(閾值可解析分析,具體方法和公式請參考後文列出的相關論文)時存在嚴重的失效,因此不適合在實際中單獨使用。一種例外是,如果對節省儲存空間要求不強烈,不要求空間複雜度為常數(Linear Counting的空間複雜度為\(O(n)\),其它演算法均為\(O(1)\)),則在保證bitmap全滿概率很小的條件下,Linear Counting的效果要優於其它演算法。
  • 總體來看,不論哪種演算法,提高分桶數都可以降低偏差和方差,因此總體來看基數估計演算法中分桶數的選擇是最重要的一個權衡——在精度和儲存空間間的權衡。
  • 實際中,Adaptive Counting或HyperLogLog Counting都是不錯的選擇,前者偏差較小,後者對離群點容忍性更好,方差較小。
  • Google的HyperLogLog Counting++演算法屬於實驗性改進,缺乏嚴格的數學分析基礎,通用性存疑,不宜在實際中貿然使用。

參考文獻

[1] K.-Y. Whang, B. T. Vander-Zanden, and H. M. Taylor. A Linear-Time Probabilistic Counting Algorithm for Database Applications. ACM Transactions on Database Systems, 15(2):208-229, 1990.

[2] Marianne Durand and Philippe Flajolet. LogLog counting of large cardinalities. In ESA03, volume 2832 of LNCS, pages 605b 617, 2003.

[3] Min Cai, Jianping Pan, Yu K. Kwok, and Kai Hwang. Fast and accurate traffic matrix measurement using adaptive cardinality counting. In MineNet b 05: Proceedings of the 2005 ACM SIGCOMM workshop on Mining network data, pages 205b 206, New York, NY, USA, 2005. ACM.

[4] P. Flajolet, E. Fusy, O. Gandouet, and F. Meunier. Hyperloglog: The analysis of a near-optimal cardinality estimation algorithm. Disc. Math. and Theor. Comp. Sci., AH:127-146, 2007.

[5] HyperLogLog in Practice: Algorithmic Engineering of a State of The Art Cardinality Estimation Algorithm.

[6] Appendix to HyperLogLog in Practice: Algorithmic Engineering of a State of the Art Cardinality Estimation Algorithm.

相關推薦

常用基數估計演算法效果實驗實踐建議

之前我曾寫過一系列關於基數估計(cardinality estimation)演算法的文章,文中介紹了一些常用基數估計演算法的原理。最近對常用的基數估計演算法做了一些實驗,這篇文章描述了實驗結果,包括這些演算法的估計效果及誤差狀況,主要通過圖表展示。通過觀察實驗資料和視覺

常用的排序演算法

什麼是演算法 我想很多程式設計師恐怕誤解了「演算法」的意義,一想到演算法就是動態規劃,機器學習之類的高大名詞。演算法其實就是數學中的「解題過程」,解題過程要求精確,考慮各種情況,需要人看得懂。演算法不需要你在鍵盤上選擇什麼程式語言實現,只需要在本子上詳細的寫出每一個步驟就可以了。 演算法真的很重要嗎?

常用的排序演算法

<script type="text/javascript"> //氣泡排序 function bubbleSort(arr){ var i = j = 0; for(i=1;i<arr.length;i++){ for(j

視覺直觀感受 7 常用的排序演算法

1. 快速排序 介紹: 快速排序是由東尼·霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 演算法更快,因為它的內部迴圈

常用內部排序演算法總結

在公司實習了,由於公司的性質,以後的工作中用到演算法&資料結構的知識可能會很少,很想把以前學的資料結構&演算法的知識系統的回憶一下,但由於時間的原因,再加上我一直都很喜歡排序演算法的思想。近期主要就排序這個問題做一個系統的介紹:氣泡排序,簡單選擇排序,直接插

常用web伺服器jvm引數設定

 一、tomcat Tomcat預設可以使用的記憶體為128MB,在較大型的應用專案中,這點記憶體是不夠的,需要調大。有以下幾種方法可以選用:第一種方法:在配置檔案中設定Windows下,在檔案/bin/catalina.bat,Unix下,在檔案/bin/catali

常用的排序演算法(c語言實現)

概述 最近重新回顧了一下資料結構和演算法的一些基本知識,對幾種排序演算法有了更多的理解,也趁此機會通過部落格做一個總結。 1.選擇排序-簡單選擇排序 選擇排序是最簡單的一種基於O(n2)時間複雜度的排序演算法,基本思想是從i=0位置開始到i=n-1

基數估計演算法(一):Flajolet-Martin演算法

簡介 基礎版 標準版 TIPs 參考資料 簡介 說起基數估計演算法的始祖,或許就是由Flajolet和Martin大佬發表的論文《 Probabilistic counting algorithms for data base appli

常用的排序演算法(快速排序,希爾排序,堆排序,選擇排序,氣泡排序)

1、歸併排序      基本原理:歸併排序也稱合併排序,其演算法思想是將待排序序列分為兩部分,依次對分得的兩個部分再次使用歸併排序,之後再對其進行合併。操作步驟如下。(1)將所要進行的排序序列分為左右兩個部分,如果要進行排序的序列的起始元素下標為first,最後一個元素的

常用的MySQL圖形化管理工具

MySQL Workbench 為資料庫管理員、程式開發者和系統規劃師提供視覺化設計、模型建立、以及資料庫管理功能。它包含了用於建立複雜的資料建模ER模型,正向和逆向資料庫工程,也可以用於執行通常需要花費大量時間和需要的難以變更和管理的文件任務。MySQL工作臺可在Windows,Linux和Mac上使用。

7 常用的排序演算法直觀感受

1. 快速排序 介紹: 快速排序是由東尼·霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 演算法更快,因為它的

實驗七 儲存管理---------常用頁面置換演算法模擬實驗

 實驗七 儲存管理---------常用頁面置換演算法模擬實驗 實驗目的通過模擬實現請求頁式儲存管理的幾種基本頁面置換演算法,瞭解虛擬儲存技術的特點,掌握虛擬儲存請求頁式儲存管理中幾種基本頁面置換演算法的基本思想和實現過程,並比較它們的效率。 實驗內容設計一個虛擬儲存區和記憶

redis的常用資料結構

Redis是什麼?     Redis:Remote Dictionary Server (遠端字典伺服器)。是一個k/V記憶體資料庫,基於記憶體執行。     支援資料持久化,可將記憶體中的資料保持

常用的排序演算法(一)--python實現

1. 選擇排序,時間複雜度O(n^2),演算法不穩定。     思路:(1)迴圈整個陣列 arr,選出最大的數,將它放在空陣列 new_arr 的第一個位置。                (2)將剛

基數估計演算法

在我們的業務場景中需要計算UV或者IP之類的bitmap資訊,使用hashset之類的解決方案對記憶體開銷較大,因此引入了基數估算,當前的應用是使用JAVA。下面給出一些測試資料。 AdaptiveCounting庫: <dependency>        

基數估計演算法(二):Linear Counting演算法

簡介 Linear Counting是KYU-YOUNG WHANG,BRAD T. VANDER-ZANDEN和HOWARD M. TAYLOR大佬們1990年發表的論文《A linear-time probabilistic counting

PHP常用的設計模式——工廠模式

一直對設計模式有一種敬畏之心,每次想要看設計模式的時候就會想到Erich Gamma,Richard Helm , Ralph Johnson, John Vlissides的黑皮《設計模式》,基本都望而止步,要把那本書看完可不是一時半會的,而且在沒有專案經驗的

圖的最短路徑演算法

本文總結了圖的幾種最短路徑演算法的實現:深度或廣度優先搜尋演算法,費羅伊德演算法,迪傑斯特拉演算法,Bellman-Ford 演算法。1)深度或廣度優先搜尋演算法(解決單源最短路徑)從起點開始訪問所有深度遍歷路徑或廣度優先路徑,則到達終點節點的路徑有多條,取其中路徑權值最短的

獲得系統時間的常用方法

1.使用CTime類(獲取系統當前時間,精確到秒) CString str; //獲取系統時間 CTime tm; tm=CTime::GetCurrentTime();//獲取系統日期 str=tm.Format("現在時間是%Y年%m月%d日 %X"); Message

詳解FSMO的角色和FSMO角色辨別方法角色轉換方法

FSMO中文翻譯成操作主控,在說明FSMO的作用以前,先給大家介紹兩個概念: 單主複製:所謂的單主複製就是指從一個地方向其它地方進行復制,這個主要是用於以前的NT4域,我們知道,在NT4域的年代,域網路上區分PDC和BDC,所有的複製都是從PDC到BDC上進行的,因為NT4域用的是這種複製機構