O RoaringBitmap pré-agrega contagens de visitantes únicos (UV) em bitmaps compactados durante cada atualização incremental, o que reduz o processamento da consulta a um cálculo de cardinalidade sobre bitmaps. Combinada à atualização incremental da Dynamic Table — que processa apenas linhas novas, dispensa agendamento manual e atende a consultas de qualquer intervalo de tempo —, essa abordagem fornece cálculos de UV em menos de um segundo para centenas de milhões de registros, mesmo em cargas de trabalho com alto QPS e baixa latência.
Escolha a implementação conforme o tipo do campo UID:
|
Tipo de UID |
Método |
|
|
|
|
|
O RoaringBitmap opera com entradas inteiras. Para campos UID do tipoint, não é necessária conversão. Para campos UID do tipotext(Método 2), uma tabela de mapeamento converte os UIDs de texto em valoresint4antes da agregação.
Quando usar esta abordagem
Use o RoaringBitmap com Dynamic Table quando:
O volume de dados atingir centenas de milhões de registros ou mais
As consultas exigirem alto QPS com baixa latência
Os cálculos de UV precisarem abranger intervalos de tempo arbitrários
Pré-requisitos
Antes de começar, verifique se você tem:
Uma instância Hologres com permissões para criar tabelas e Dynamic Tables
A extensão RoaringBitmap instalada
Instale a extensão antes de criar tabelas ou Dynamic Tables:
CREATE EXTENSION IF NOT EXISTS roaringbitmap;
Método 1: UV com RoaringBitmap para campos INT
Use este método quando o campo UID for do tipo int. Ele permite operações de interseção, união e diferença em grupos de usuários com base em qualquer tag ou propriedade.
Como funciona
Armazene dados granulares de eventos em uma tabela de detalhes particionada por dia.
Uma Dynamic Table lê a tabela de detalhes incrementalmente, agrupa linhas por dimensões de negócio e agrega UIDs em um RoaringBitmap por grupo usando
RB_BUILD_AGG. Cada linha na Dynamic Table contém um bitmap que representa todos os UIDs distintos para aquela combinação de dimensão e data.Durante a consulta,
RB_OR_AGGmescla bitmaps no intervalo de datas solicitado — deduplicando UIDs entre dias — eRB_CARDINALITYretorna a contagem de UV.
Crie a tabela de detalhes
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;
A tabela é particionada por ymd (formato YYYYMMDD) para permitir poda eficiente de partições durante a consulta. A propriedade bitmap_columns acelera a filtragem em country, prov, city e ymd.
Crie a Dynamic Table
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, -- aggregates all UIDs in the group into a RoaringBitmap
country,
prov,
city,
ymd,
COUNT(1) AS pv
FROM ods_app_detail
GROUP BY country, prov, city, ymd;
A Dynamic Table atualiza apenas a partição ativa (do último dia) a cada 5 minutos e processa exclusivamente linhas novas. Após cada atualização, cada linha em dt_dws_app_rb contém um bitmap rb_uid para uma combinação específica de (country, prov, city, ymd), representando todos os UIDs distintos que apareceram naquela data com esses valores de dimensão. Por exemplo, a linha correspondente a (US, California, San Francisco, 20251223) armazena um único bitmap com cada UID deduplicado que acessou o sistema nessa data.
Atualizar partições históricas
Novas partições são atualizadas automaticamente. Para partições históricas fora da janela ativa, execute uma atualização completa manualmente. Por exemplo, para preencher retroativamente os dados de 1º de dezembro de 2025:
REFRESH DYNAMIC TABLE public.dt_dws_app_rb PARTITION(20251201) WITH (refresh_mode = 'full');
Consultar UV em qualquer intervalo de tempo
Ambas as consultas usam RB_OR_AGG para unir bitmaps entre linhas — deduplicando UIDs entre grupos de dimensões e datas — e, em seguida, aplicam RB_CARDINALITY para contar os UIDs distintos.
-- UV and PV for a single day
SELECT
RB_CARDINALITY(RB_OR_AGG(rb_uid)) AS uv, -- union bitmaps across rows, then count distinct UIDs
country,
prov,
city,
SUM(pv) AS pv
FROM dt_dws_app_rb
WHERE ymd = '20251223'
GROUP BY country, prov, city;
-- UV and PV for a month
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;
Método 2: UV com RoaringBitmap para campos TEXT
Use este método quando o campo UID for do tipo text. Como o RoaringBitmap exige entradas inteiras, uma tabela de mapeamento de usuários armazena a conversão de text para int4. A função hg_id_encoding_int4 faz essa conversão automaticamente dentro da Dynamic Table: ela consulta ou insere cada UID de texto na tabela de mapeamento e retorna seu equivalente inteiro. Assim, você não precisa gerenciar o dicionário manualmente nem executar jobs de junção separados.
Crie a tabela de mapeamento de usuários
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;
A tabela de mapeamento usa armazenamento orientado a linhas para garantir buscas pontuais rápidas por uid. A coluna uid_int32 serial atribui automaticamente um inteiro exclusivo a cada novo UID de texto.
Crie a Dynamic Table
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, -- aggregates mapped integer UIDs into a RoaringBitmap
ymd
FROM (
SELECT
country,
prov,
city,
hg_id_encoding_int4(uid, 'uid_mapping') AS uid_int4, -- converts text UID to int4, writes new entries to uid_mapping
ymd
FROM ods_app_detail
) a
GROUP BY country, prov, city, ymd;
A subconsulta chama hg_id_encoding_int4(uid, 'uid_mapping') para consultar ou inserir cada UID de texto em uid_mapping e retornar seu equivalente inteiro. A consulta externa agrega esses inteiros em bitmaps por grupo de dimensão.
Consultar UV em qualquer intervalo de tempo
SELECT
country,
prov,
city,
RB_CARDINALITY(RB_OR_AGG(uid_rb)) AS uv -- union bitmaps across rows, then count distinct UIDs
FROM dt_dws_app_rb
WHERE ymd = '20251223'
GROUP BY country, prov, city;
Estenda a cláusula WHERE para qualquer intervalo de datas, seguindo a mesma lógica do Método 1.