Todos os produtos
Search
Central de documentação

Hologres:Calcular UV com tabela dinâmica e roaring bitmaps

Última atualização: Jun 28, 2026

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

int

Método 1: UV com RoaringBitmap para campos INT

text

Método 2: UV com RoaringBitmap para campos TEXT

O RoaringBitmap opera com entradas inteiras. Para campos UID do tipo int , não é necessária conversão. Para campos UID do tipo text (Método 2), uma tabela de mapeamento converte os UIDs de texto em valores int4 antes 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

  1. Armazene dados granulares de eventos em uma tabela de detalhes particionada por dia.

  2. 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.

  3. Durante a consulta, RB_OR_AGG mescla bitmaps no intervalo de datas solicitado — deduplicando UIDs entre dias — e RB_CARDINALITY retorna 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.

Próximos passos