Um HyperLogLog é uma estrutura de dados probabilística . Conta o número de elementos distintos em uma lista. Mas, em comparação com uma maneira simples de fazer isso (ter um conjunto e adicionar elementos ao conjunto), ele faz isso de maneira aproximada.
Antes de analisar como o algoritmo HyperLogLog faz isso, é preciso entender por que você precisa dele. O problema de maneira direta é que consome O(distinct elements)
espaço. Por que existe uma grande notação O aqui em vez de apenas elementos distintos? Isso ocorre porque os elementos podem ter tamanhos diferentes. Um elemento pode ser 1
outro elemento "is this big string"
. Portanto, se você tiver uma lista enorme (ou um fluxo enorme de elementos), será necessária muita memória.
Contagem Probabilística
Como se pode obter uma estimativa razoável de vários elementos únicos? Suponha que você tenha uma cadeia de comprimento m
que consiste {0, 1}
em igual probabilidade. Qual é a probabilidade de começar com 0, com 2 zeros, com k zeros? É 1/2
, 1/4
e 1/2^k
. Isso significa que, se você encontrou uma string com k
zeros, examinou aproximadamente os 2^k
elementos. Portanto, este é um bom ponto de partida. Ter uma lista de elementos que são distribuídos igualmente entre 0
e 2^k - 1
você pode contar o número máximo do maior prefixo de zeros na representação binária e isso fornecerá uma estimativa razoável.
O problema é que a suposição de ter números uniformemente distribuídos de 0
t 2^k-1
é muito difícil de alcançar (os dados que encontramos geralmente não são números, quase nunca distribuídos uniformemente e podem estar entre quaisquer valores. Mas, usando uma boa função de hash, você pode assumir que os bits de saída seriam distribuídos uniformemente e a maioria das funções de hash tem saídas entre 0
e 2^k - 1
( SHA1 fornece valores entre 0
e 2^160
). Portanto, o que alcançamos até agora é que podemos estimar o número de elementos únicos com a cardinalidade máxima de k
bits armazenando apenas um número de log(k)
bits de tamanho.A desvantagem é que temos uma enorme variação em nossa estimativa.Uma coisa legal que quase criamosPapel probabilístico de contagem de 1984 (é um pouco mais inteligente com a estimativa, mas ainda estamos perto).
LogLog
Antes de avançarmos, precisamos entender por que nossa primeira estimativa não é tão boa. A razão por trás disso é que uma ocorrência aleatória de elemento de prefixo 0 de alta frequência pode estragar tudo. Uma maneira de aprimorá-lo é usar muitas funções de hash, contar no máximo para cada uma das funções de hash e, no final, calculá-las. Essa é uma excelente idéia, que melhorará a estimativa, mas o papel LogLog usou uma abordagem ligeiramente diferente (provavelmente porque o hash é meio caro).
Eles usaram um hash, mas o dividiram em duas partes. Um é chamado de balde (o número total de baldes é 2^x
) e outro - é basicamente o mesmo que o nosso hash. Foi difícil para mim entender o que estava acontecendo, então vou dar um exemplo. Suponha que você tenha dois elementos e sua função hash, que fornece valores 0
aos 2^10
2 valores produzidos: 344
e 387
. Você decidiu ter 16 baldes. Então você tem:
0101 011000 bucket 5 will store 1
0110 000011 bucket 6 will store 4
Ao ter mais baldes, você diminui a variação (você usa um pouco mais de espaço, mas ainda é pequeno). Usando habilidades matemáticas, eles foram capazes de quantificar o erro (que é 1.3/sqrt(number of buckets)
).
HyperLogLog
O HyperLogLog não apresenta novas idéias, mas usa principalmente muita matemática para melhorar a estimativa anterior. Os pesquisadores descobriram que, se você remover 30% dos maiores números dos baldes, melhorará significativamente a estimativa. Eles também usaram outro algoritmo para calcular a média dos números. O papel é pesado em matemática.
E quero terminar com um artigo recente, que mostra uma versão aprimorada do algoritmo hyperLogLog (até agora não tinha tempo para entendê-lo completamente, mas talvez mais tarde aprimore essa resposta).