Un HyperLogLog es una estructura de datos probabilística . Cuenta el número de elementos distintos en una lista. Pero en comparación con una forma directa de hacerlo (tener un conjunto y agregar elementos al conjunto) lo hace de manera aproximada.
Antes de ver cómo el algoritmo HyperLogLog hace esto, uno tiene que entender por qué lo necesita. El problema con una forma directa es que consumeO(distinct elements)
espacio. ¿Por qué hay una gran notación O aquí en lugar de solo elementos distintos? Esto se debe a que los elementos pueden ser de diferentes tamaños. Un elemento puede ser 1
otro elemento "is this big string"
. Entonces, si tiene una lista enorme (o una gran corriente de elementos), le tomará mucha memoria.
Conteo probabilístico
¿Cómo se puede obtener una estimación razonable de varios elementos únicos? Suponga que tiene una cadena de longitud m
que consta de {0, 1}
igual probabilidad. ¿Cuál es la probabilidad de que comience con 0, con 2 ceros, con k ceros? Es 1/2
, 1/4
y 1/2^k
. Esto significa que si ha encontrado una cadena con k
ceros, ha examinado aproximadamente los 2^k
elementos. Entonces este es un buen punto de partida. Tener una lista de elementos que se distribuyen uniformemente 0
y 2^k - 1
puede contar el número máximo del prefijo más grande de ceros en representación binaria y esto le dará una estimación razonable.
El problema es que la suposición de tener números distribuidos uniformemente desde 0
t 2^k-1
es demasiado difícil de lograr (los datos que encontramos no son en su mayoría números, casi nunca se distribuyen de manera uniforme, y pueden estar entre cualquier valor. Pero al usar una buena función de hash puedes asumir que los bits de salida se distribuirían uniformemente y la mayoría de las funciones de hashing tienen salidas entre 0
y2^k - 1
( SHA1 le da valores entre0
y 2^160
). Entonces, lo que hemos logrado hasta ahora es que podemos estimar el número de elementos únicos con la cardinalidad máxima de k
bits almacenando solo un número de log(k)
bits de tamaño . La desventaja es que tenemos una gran variación en nuestra estimación. Una cosa genial que casi creamosDocumento de conteo probabilístico de 1984 (es un poco más inteligente con la estimación, pero aún estamos cerca).
LogLog
Antes de continuar, tenemos que entender por qué nuestra primera estimación no es tan buena. La razón detrás de esto es que una ocurrencia aleatoria del elemento de prefijo 0 de alta frecuencia puede estropear todo. Una forma de mejorarlo es usar muchas funciones hash, contar el máximo para cada una de las funciones hash y al final promediarlas. Esta es una idea excelente, que mejorará la estimación, pero el papel LogLog utilizó un enfoque ligeramente diferente (probablemente porque el hashing es algo costoso).
Usaron un hash pero lo dividieron en dos partes. Uno se llama un cubo (el número total de cubos es 2^x
) y otro, es básicamente el mismo que nuestro hash. Fue difícil para mí entender lo que estaba pasando, así que daré un ejemplo. Suponga que tiene dos elementos y su función hash que le da forma 0
a los valores para 2^10
producir 2 valores: 344
y 387
. Decidiste tener 16 cubos. Así que tienes:
0101 011000 bucket 5 will store 1
0110 000011 bucket 6 will store 4
Al tener más cubos, disminuye la variación (usa un poco más de espacio, pero aún es pequeño). Usando habilidades matemáticas, pudieron cuantificar el error (que es 1.3/sqrt(number of buckets)
).
HyperLogLog
HyperLogLog no introduce ninguna idea nueva, pero en su mayoría utiliza muchas matemáticas para mejorar la estimación anterior. Los investigadores han descubierto que si eliminas el 30% de los números más grandes de los cubos, mejorarás significativamente la estimación. También usaron otro algoritmo para promediar números. El papel es matemático pesado.
Y quiero terminar con un artículo reciente, que muestra una versión mejorada del algoritmo hyperLogLog (hasta ahora no tenía tiempo para entenderlo completamente, pero tal vez más adelante mejoraré esta respuesta).