EN
返回档案库

案例库 · 研发与科研 · 技术决策 · 2007-2013

HyperLogLog 用千字节计数数十亿个不同元素

Flajolet 的草图通过哈希前导零的最长运行估算你见过的唯一元素数量——1.5 kB 内存,而不是每个元素占用内存。

INRIA

那一手

精确基数——即出现了多少不同的用户、IP 地址或搜索查询——通常需要与不同元素数量成正比的内存,这在互联网规模下是不可能的。2007 年,Philippe Flajolet 和 INRIA 的同事发表了 HyperLogLog,这是一种概率草图,能以约 2% 的准确率估算超过十亿的基数,仅需约 1.5 千字节内存。

这个技巧基于抛硬币的直觉:将每个元素哈希成一个均匀分布的随机数,观察最长的前导零序列。出现 n 个零的概率是 2 的负 n 次方,非常小——所以当它出现时,集合很可能足够大才会产生它,因此 2 的 n 次方是对基数的一个良好估计。HyperLogLog 将数据流分成多个子集,每个子集保留一个寄存器来存储其最长的零序列,然后用调和平均合并它们,这样异常值就不会扭曲估计。

该方法源自 Flajolet-Martin 1984 年的算法和 LogLog 算法。使其可用于生产的工程改进出现在 2013 年 Google 的 Heule、Nunkesser 和 Hall 发表的论文《HyperLogLog in Practice》中,该论文修复了大基数和小基数下的偏差和稀疏性问题。

Redis 将 HyperLogLog 作为一项产品功能:其 PFADD、PFCOUNT 和 PFMERGE 命令可以估算多达 2 的 64 次方个不同元素,每个键使用最多 12 KB 内存,标准误差为 0.81%,并且草图可以合并,因此每日计数无需重新读取原始数据流即可组合。

为什么管用

  • 哈希将任意数据转换为同基数下的均匀随机数
  • 最长的前导零序列是衡量集合大小的自然且可观察的估计
  • 拆分成寄存器并取调和平均可以消除噪声
  • 草图可合并,因此无需存储原始流即可组合每日计数
值了多少从哈希前导零估算计数聪明

可以搬走什么

当答案只需要近似时,停止存储数据——存储一个微型草图,其随机性揭示规模,用有界误差换取无限扩展。

后来呢

HyperLogLog 成为分析和数据库中的标准构件:Redis 将其作为数据类型,2013 年 Google 论文的改进使其在生成环境中大规模可用。该草图的逻辑——保存证据的小记录,而不是数据——也奠定了后来的 MinHash 和 Count-Min Sketch 等结构的基础。

资料来源

发现哪里写错了?告诉我们。

同一路聪明