O uso de COUNT DISTINCT exige uma varredura completa dos dados brutos a cada execução, o que impede respostas eficientes para consultas com múltiplos segmentos. A extensão hll adiciona o tipo de dado HyperLogLog (HLL) ao PolarDB for PostgreSQL, permitindo armazenar sketches probabilísticos em vez de linhas brutas. Assim, é possível estimar contagens de valores distintos — como visualizações de página (PVs) e visitantes únicos (UVs) — com margem de erro controlada, uso constante de memória e consultas instantâneas de união entre vários dias ou segmentos.
Na prática, 1.280 bytes de dados hll conseguem estimar com precisão bilhões de elementos distintos.
Versões suportadas
A extensão hll é compatível com clusters do PolarDB for PostgreSQL nas seguintes versões:
PostgreSQL 14 (versão de revisão 14.5.1.0 ou posterior)
PostgreSQL 11 (versão de revisão 1.1.28 ou posterior)
Para verifique a versão de revisão em uso:
-
PostgreSQL 14:
SELECT version(); -
PostgreSQL 11:
SHOW polar_version;
Funcionamento
O HyperLogLog utiliza uma hierarquia de representações internas para minimizar o uso de memória em baixas cardinalidades e alternar para uma estrutura probabilística compacta conforme a cardinalidade aumenta:
|
Representação |
Descrição |
|
EMPTY |
Conjunto vazio. |
|
EXPLICIT |
Utilizado em baixas cardinalidades. |
|
SPARSE |
Aplicado em cardinalidades intermediárias. |
|
FULL |
Destinado a altas cardinalidades. |
A função hll_print exibe a representação ativa e seus parâmetros, sendo útil para ajustes e depuração.
Tipos de dados
|
Tipo |
Descrição |
|
|
Armazena um sketch HyperLogLog. Suporta agregação, união e estimativa de cardinalidade. |
|
|
Valor de hash intermediário. As funções de hash geram este tipo antes da agregação dos valores em um |
Instalação e remoção da extensão
Instale a extensão:
CREATE EXTENSION hll;
Remova a extensão:
DROP EXTENSION hll;
Funções de hash
As funções de hash convertem valores brutos de colunas para hll_hashval antes da agregação em um hll. Escolha a função correspondente ao tipo da sua coluna de source.
|
Função |
Tipo de entrada |
Exemplo |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Exemplos:
-
SELECT hll_hash_boolean(true);Resultado:hll_hash_boolean --------------------- 8849112093580131862 (1 row) -
SELECT hll_hash_integer(1);Resultado:hll_hash_integer ---------------------- -8604791237420463362 (1 row)
Operadores
Operadores hll
|
Operador |
Descrição |
Exemplo |
Resultado |
||||
|
|
Igualdade |
|
|
||||
|
|
Desigualdade |
— |
— |
||||
|
|
` |
União de dois valores |
|
hll_add_agg(2::hll_hashval)` |
|
||
|
|
Estimativa de cardinalidade (contagem distinta) |
|
|
Operadores hll_hashval
|
Operador |
Descrição |
Exemplo |
Resultado |
|
|
Igualdade |
|
|
|
|
Desigualdade |
|
|
Operações básicas
Converta dados INT para hll_hashval:
SELECT 1::hll_hashval;
Resultado:
hll_hashval
-------------
1
(1 row)
Funções
hll_add_agg
Agrega valores hll_hashval em um único valor hll.
SELECT hll_add_agg(1::hll_hashval);
Resultado:
hll_add_agg
--------------------------
\x128b7f0000000000000001
(1 row)
hll_union
Combina dois valores hll em um só.
SELECT hll_union(hll_add_agg(1::hll_hashval), hll_add_agg(2::hll_hashval));
Resultado:
hll_union
------------------------------------------
\x128b7f00000000000000010000000000000002
(1 row)
hll_set_defaults
Defina os parâmetros de precisão.
SELECT hll_set_defaults(15, 5, -1, 1);
Resultado:
hll_set_defaults
------------------
(11,5,-1,1)
(1 row)
hll_print
Exibe a representação interna e os parâmetros de um valor hll. Utilize esta função para inspecionar o algoritmo ativo e verifique as configurações de precisão.
SELECT hll_print(hll_add_agg(1::hll_hashval));
Resultado:
hll_print
-----------------------------------------------------------------------------
EXPLICIT, 1 elements, nregs=32768, nbits=5, expthresh=-1(2560), sparseon=1:+
0: 1
(1 row)
Exemplo completo: rastreamento diário de UV
Este exemplo demonstra o fluxo completo: aplicação de hash em IDs de usuário brutos, agregação em valores hll por dia, consulta de contagens diárias de usuários distintos e combinação de múltiplos dias via união.
Etapa 1: Crie e popular a tabela de agregação
CREATE TABLE access_date (acc_date DATE UNIQUE, userids hll);
-- Day 0: users with IDs 1-10000
INSERT INTO access_date
SELECT current_date, hll_add_agg(hll_hash_integer(user_id))
FROM generate_series(1, 10000) t(user_id);
-- Day -1: users with IDs 5000-20000
INSERT INTO access_date
SELECT current_date - 1, hll_add_agg(hll_hash_integer(user_id))
FROM generate_series(5000, 20000) t(user_id);
-- Day -2: users with IDs 9000-40000
INSERT INTO access_date
SELECT current_date - 2, hll_add_agg(hll_hash_integer(user_id))
FROM generate_series(9000, 40000) t(user_id);
Etapa 2: Consultar contagens diárias de usuários distintos
Utilize o operador # para estimar os UVs de cada dia:
SELECT #userids FROM access_date WHERE acc_date = current_date;
Resultado:
?column?
------------------
9725.852733707077
(1 row)
SELECT #userids FROM access_date WHERE acc_date = current_date - 1;
Resultado:
?column?
------------------
14968.65968832792
(1 row)
SELECT #userids FROM access_date WHERE acc_date = current_date - 2;
Resultado:
?column?
------------------
29361.520914991113
(1 row)