おおよその重複排除に HLL を使用する
背景
現実のシナリオでは、データ量が増えるにつれてデータの重複排除の圧力が増します。データサイズがあるレベルに達すると、正確な重複排除のコストは比較的高くなります。この場合、ユーザーは通常、計算の圧力を軽減するためにおおよそのアルゴリズムを使用します。このセクションで紹介する HyperLogLog (HLL) は、優れた空間複雑度 O(mloglogn) と時間複雑度 O(n) を持つおおよその重複排除アルゴリズムです。さらに、計算結果の誤差率はデータセットのサイズと使用されるハッシュ関数に応じて約 1%~10% に制御できます。
HyperLogLog とは
HyperLogLog は、非常に少ないストレージスペースを消費するおおよその重複排除アルゴリズムです。HLL タイプは HyperLogLog アルゴリズムを実装するために使用されます。これは HyperLogLog 計算の中間結果を保持し、データテーブルのインジケーター列タイプとしてのみ使用できます。
HLL アルゴリズムは多くの数学的知識を含むため、実用的な例を使用して説明します。コインを最初に表が出るまで独立して繰り返し投げるランダム化実験 A を設計し、最初に表が出るまでのコイン投げの回数をランダム変数 X として記録します。すると:
- X=1, P(X=1)=1/2
- X=2, P(X=2)=1/4
- ...
- X=n, P(X=n)=(1/2)n
テスト A を使用してランダム化テスト B を構築します。これは、テスト A を N 回独立して繰り返し、N 個の独立した同一分布のランダム変数 X1, X2, X3, ..., XN を生成します。ランダム変数の最大値を Xmax とします。大きな尤度推定を利用して、N の推定値は 2Xmax です。
与えられたデータセットに対してハッシュ関数を使用して上記の実験をシミュレートします:
- テスト A: データセット要素のハッシュ値を計算し、ハッシュ値をバイナリ表現に変換します。バイナリの最下位ビットから始めて、ビット=1 の出現を記録します。
- テスト B: テスト B のデータセット要素に対してテスト A のプロセスを繰り返します。各テストで最初のビット 1 の出現の最大位置 "m" を更新します。
- データセット内の非重複要素の数を m2 として推定します。
実際には、HLL アルゴリズムは要素を K=2k バケットに分割し、要素ハッシュの下位 k ビットに基づいています。k+1 ビットから最初のビット 1 の出現の最大値を m1, m2,..., mk としてカウントし、バケット内の非重複要素の数を 2m1, 2m2,..., 2mk として推定します。データセット内の非重複要素の数は、バケットの数とバケット内の非重複要素の数を掛けた合計平均です:N = K(K/(2-m1+2-m2,..., 2-mK))。
HLL は推定結果に補正係数を掛けて結果をより正確にします。
StarRocks SQL ステートメントを使用して HLL 重複排除アルゴリズムを実装する方法については、記事 https://gist.github.com/avibryant/8275649 を参照してください。
SELECT floor((0.721 * 1024 * 1024) / (sum(pow(2, m * -1)) + 1024 - count(*))) AS estimate
FROM(select(murmur_hash3_32(c2) & 1023) AS bucket,
max((31 - CAST(log2(murmur_hash3_32(c2) & 2147483647) AS INT))) AS m
FROM db0.table0
GROUP BY bucket) bucket_values
このアルゴリズムは db0.table0 の col2 を重複排除します。
- ハッシュ関数
murmur_hash3_32を使用して col2 のハッシュ値を 32 ビット符号付き整数として計算します。 - 1024 バケットを使用し、補正係数は 0.721 で、ハッシュ値の下位 10 ビットをバケットの添字として使用します。
- ハッシュ値の符号ビットを無視し、次の最高ビットから下位ビットまで、最初のビット 1 の出現位置を決定します。
- 計算されたハッシュ値をバケットでグループ化し、
MAX集計を使用してバケット内の最初のビット 1 の出現の最大位置を見つけます。 - 集計結果をサブクエリとして使用し、すべてのバケット推定値の合計平均にバケット数と補正係数を掛けます。
- 空のバケット数は 1 であることに注意してください。
データ量が多い場合、このアルゴリズムの誤差率は非常に低くなります。
これが HLL アルゴリズムの核心的なアイデアです。興味がある方は HyperLogLog 論文 を参照してください。