ビットマップを使用した正確な Count Distinct
このトピックでは、StarRocks でビットマップを使用して異なる値の数を計算する方法について説明します。
ビットマップは、配列内の異なる値の数を計算するのに便利なツールです。この方法は、従来の Count Distinct と比較して、ストレージスペースを節約し、計算を高速化できます。配列 A が [0, n) の範囲の値を持つと仮定します。(n+7)/8 バイトのビットマップを使用することで、配列内の異なる要素の数を計算できます。これを行うには、すべてのビットを 0 に初期化し、要素の値をビットの添字として設定し、すべてのビットを 1 に設定します。ビットマップ内の 1 の数が、配列内の異なる要素の数です。
従来の Count Distinct
StarRocks は MPP アーキテクチャを使用しており、Count Distinct を使用する際に詳細データを保持できます。しかし、Count Distinct 機能はクエリ処理中に複数のデータシャッフルを必要とし、リソースを多く消費し、データ量が増えるにつれてパフォーマンスが線形に低下します。
次のシナリオでは、テーブル (dt, page, user_id) の詳細データに基づいて UV を計算します。
| dt | page | user_id |
|---|---|---|
| 20191206 | game | 101 |
| 20191206 | shopping | 102 |
| 20191206 | game | 101 |
| 20191206 | shopping | 101 |
| 20191206 | game | 101 |
| 20191206 | shopping | 101 |
StarRocks は次の図に従ってデータを計算します。まず、page と user_id 列でデータをグループ化し、処理された結果をカウントします。

- 注: 図は、2 つの BE ノードで計算された 6 行のデータの概略を示しています。
大規模なデータを扱う際に、複数のシャッフル操作が必要な場合、計算リソースが大幅に増加する可能性があります。これによりクエリが遅くなります。しかし、ビットマップ技術を使用することで、この問題を解決し、クエリパフォーマンスを向上させることができます。
page でグループ化して uv をカウントします:
select page, count(distinct user_id) as uv from table group by page;
| page | uv |
| :---: | :---: |
| game | 1 |
| shopping | 2 |