すべてのプロダクト
Search
ドキュメントセンター

Hologres:Hologres Dynamic Table を用いた任意の長期にわたる UV 計算ソリューション

最終更新日:Feb 07, 2026

データ量が大規模で、クエリ/秒(QPS)およびレイテンシーに厳しい要件があるビジネスシナリオでは、Hologres の RoaringBitmap と Dynamic Table を組み合わせることで、増分計算を実行し、任意の期間にわたる柔軟な UV 計算を実現できます。本トピックでは、INT 型および TEXT 型のフィールドそれぞれに対する実装方法について説明します。

ソリューションの概要

本ソリューションには以下の利点があります:Dynamic Table は増分更新を採用しており、毎回処理対象となるのは新規データのみであるため、高 QPS・低レイテンシーの UV 計算において、高いパフォーマンスと低いリソース消費を実現します。また、Dynamic Table が自動的にリフレッシュを実行するため、追加のスケジューリングタスクは不要です。クエリは柔軟で、任意の時間範囲をサポートします。本アプローチは、大規模データ(数億レコード規模)に対して、任意の長期にわたる高 QPS の UV 計算に適しています。

ビジネスシナリオおよびデータ型に応じて、RoaringBitmap の実装方法は以下の 2 種類から選択してください:

  • 方法 1:INT 型フィールド向けの長期 UV 計算 — UID が INT 型である場合の正確な重複排除に最適です。Dynamic Table と組み合わせることで、任意のタグまたはプロパティに基づくユーザーグループ間の積集合、和集合、差集合演算をサポートします。

  • 方法 2:マッピングテーブルを併用した TEXT 型フィールド — UID が TEXT 型である場合に最適です。TEXT 形式の UID を整数に変換するためのユーザーマッピングテーブルが必要です。

方法 1:INT 型フィールド向けの RoaringBitmap 長期 UV 計算

UID フィールドが int 型である場合に、大規模データ(数億レコード規模)に対して任意の長期にわたる高 QPS の UV 計算を実行する際に、本方法をご利用ください。

ワークフロー

  1. すべてのビジネスディメンションにわたる細かい粒度のデータを格納するためのユーザーデータ詳細テーブルを作成します。

  2. ビジネスロジックに基づき、ユーザーデータ詳細テーブルを増分処理する Dynamic Table を作成します。基本ディメンションでグループ化し、UID を RoaringBitmap に集約して Dynamic Table に格納します。

  3. 目的のディメンションで Dynamic Table をクエリします。RoaringBitmap フィールドに対して RB_OR_AGG を適用して重複を排除し、UV のカーディナリティおよび PV のカウントを算出します。これにより、サブセカンドレベルのクエリ応答が実現します。

基盤データの準備

使用前に RoaringBitmap 拡張機能を作成します:

CREATE EXTENSION IF NOT EXISTS roaringbitmap;

ユーザーデータ詳細テーブルを作成します(日単位のパーティション分割を推奨)。以下の例では、テーブル作成およびプロパティ設定を示しています:

DROP TABLE IF EXISTS ods_app_detail;
BEGIN;
CREATE TABLE IF NOT EXISTS ods_app_detail (
  uid int,
  country text,
  prov text,
  city text,
  ymd text NOT NULL
)
LOGICAL PARTITION BY LIST (ymd);
CALL set_table_property('ods_app_detail', 'orientation', 'column');
CALL set_table_property('ods_app_detail', 'bitmap_columns', 'country,prov,city,ymd');
CALL set_table_property('ods_app_detail', 'distribution_key', 'uid');
CALL set_table_property('ods_app_detail', 'clustering_key', 'ymd');
CALL set_table_property('ods_app_detail', 'event_time_column', 'ymd');
COMMIT;

データ処理用 Dynamic Table の作成

ディメンションごとにユーザーデータ詳細テーブルを集約し、uid に対して RB_BUILD_AGG を用いて RoaringBitmap を計算する Dynamic Table を作成します。増分更新を有効化します。以下の例では、最新のパーティションのみを対象とし、データ鮮度を 5 分間隔で保つように設定しています:

CREATE DYNAMIC TABLE dt_dws_app_rb
LOGICAL PARTITION BY LIST(ymd)
WITH (
  freshness = '5 minutes',
  auto_refresh_mode = 'incremental',
  auto_refresh_partition_active_time = '1 days',
  partition_key_time_format = 'YYYYMMDD'
)
AS
SELECT
  RB_BUILD_AGG(uid) AS rb_uid,
  country,
  prov,
  city,
  ymd,
  COUNT(1) AS pv
FROM ods_app_detail
GROUP BY country, prov, city, ymd;

過去のパーティションについては手動で REFRESH を実行します。例:

REFRESH DYNAMIC TABLE public.dt_dws_app_rb PARTITION(20251201) WITH (refresh_mode = 'full');

任意の長期にわたる UV クエリ

-- 特定の日の UV および PV をクエリ
SELECT
  RB_CARDINALITY(RB_OR_AGG(rb_uid)) AS uv,
  country,
  prov,
  city,
  sum(pv) AS pv
FROM dt_dws_app_rb
WHERE ymd = '20251223'
GROUP BY country, prov, city;
-- 1 ヶ月分の UV および PV をクエリ
SELECT
  RB_CARDINALITY(RB_OR_AGG(rb_uid)) AS uv,
  country,
  prov,
  city,
  sum(pv) AS pv
FROM dt_dws_app_rb
WHERE ymd >= '20251201' AND ymd <= '20251230'
GROUP BY country, prov, city;

方法 2:マッピングテーブルを併用した TEXT 型フィールド向けの RoaringBitmap 長期 UV 計算

UID が TEXT 型である場合に本方法をご利用ください。TEXT 形式の UID を整数にマップするユーザーマッピングテーブルと組み合わせ、RoaringBitmap 処理を実行します。Dynamic Table 内の hg_id_encoding 関数を使用することで、マッピングテーブルへの自動書き込みおよび更新が可能です。

ユーザーマッピングテーブルの作成および更新

BEGIN;
CREATE TABLE uid_mapping (
  uid text NOT NULL,
  uid_int32 serial,
  PRIMARY KEY (uid)
);
CALL set_table_property('uid_mapping', 'clustering_key', 'uid');
CALL set_table_property('uid_mapping', 'distribution_key', 'uid');
CALL set_table_property('uid_mapping', 'orientation', 'row');
COMMIT;

データ処理用 Dynamic Table の作成

Dynamic Table 内で hg_id_encoding_int4(uid, 'uid_mapping') を使用し、TEXT 形式の UID を整数にマップしてマッピングテーブルを自動的に更新します。その後、ディメンションごとに RoaringBitmap に集約します:

CREATE DYNAMIC TABLE dt_dws_app_rb
WITH (
  freshness = '5 minutes',
  auto_refresh_mode = 'incremental',
  auto_refresh_partition_active_time = '1 days',
  partition_key_time_format = 'YYYYMMDD'
)
LOGICAL PARTITION BY LIST (ymd)
AS
SELECT
  country,
  prov,
  city,
  RB_BUILD_AGG(uid_int4) AS uid_rb,
  ymd
FROM (
  SELECT
    country,
    prov,
    city,
    hg_id_encoding_int4(uid, 'uid_mapping') AS uid_int4,
    ymd
  FROM ods_app_detail
) a
GROUP BY country, prov, city, ymd;

任意の長期にわたる UV クエリ

SELECT
  country,
  prov,
  city,
  RB_CARDINALITY(RB_OR_AGG(uid_rb)) AS uv
FROM dt_dws_app_rb
WHERE ymd = '20251223'
GROUP BY country, prov, city;