全部產品
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 方案有兩種實現方式:

  • 方法 1:INT 欄位類型的長周期 UV 計算 — 適用於 UID 為 INT 類型的精確去重,結合 Dynamic Table 可做任意標籤/屬性的交並差人群基數計算。

  • 方法 2:TEXT 欄位類型結合 Mapping 表 — 適用於 UID 為 TEXT 類型的情境,需結合 user mapping 表使用。

方法 1:INT 欄位類型的 RB 長周期 UV 計算

適用情境:巨量資料量(億級)的任意長周期高 QPS 的 UV 計算,且 UID 欄位為 int 類型。

方案流程

  1. 建立使用者明細表,存放業務所有維度詳細資料。

  2. 根據商務邏輯建立 Dynamic Table,對明細表增量加工,按基礎維度 GROUP BY,將 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 加工資料

建立 Dynamic Table 對明細表按維度彙總,使用 RB_BUILD_AGG 對 uid 計算,增量重新整理,樣本僅重新整理最新分區,資料新鮮度 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;
-- 查一個月 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 欄位類型結合 Mapping 表的 RB 長周期 UV 計算

適用情境:UID 為 text 類型,需結合 user mapping 表將 text 映射為 int 後使用 RoaringBitmap。可通過 hg_id_encoding 函數在 Dynamic Table 中自動寫入與更新 mapping 表。

建立與更新使用者 Mapping 表

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 映射為 int 並自動寫入 mapping 表,再按維度彙總 RB:

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;