HyperLogLog数据结构

2023-11-17

基数计数(cardinality counting) 通常用来统计一个集合中不重复的元素个数,例如统计某个网站的UV,或者用户搜索网站的关键词数量。数据分析、网络监控及数据库优化等领域都会涉及到基数计数的需求。
要实现基数计数,最简单的做法是记录集合中所有不重复的元素集合,当新来一个元素,若集合中不包含元素,则将加入,否则不加入,计数值就是的元素数量。这种做法存在两个问题:

  1. 当统计的数据量变大时,相应的存储内存也会线性增长
  2. 当集合变大,判断其是否包含新加入元素的成本变大

在redis 中,如果我们不需要获取数据集的内容,而只是想得到不同值的个数,那么就可以使用HyperLogLog( HLL)数据类型来优化使用集合类型时存在的内存和性能问题。

用法示例:

doitedu03:6379> PFADD HN:CS abc
(integer) 1
doitedu03:6379> PFADD HN:CS bbb
(integer) 1
doitedu03:6379> PFADD HN:CS ccc
(integer) 1
doitedu03:6379> PFADD HN:CS bbc
(integer) 1
doitedu03:6379> PFADD HN:CS bbc
(integer) 0
doitedu03:6379> PFCOUNT HN:CS
(integer) 4
 
doitedu03:6379> PFADD HN:ZZ bbb
(integer) 1
doitedu03:6379> PFADD HN:ZZ ccc
(integer) 1
doitedu03:6379> PFADD HN:ZZ ddd
(integer) 1
doitedu03:6379> PFADD HN:ZZ eee
(integer) 1
doitedu03:6379> PFCOUNT HN:ZZ
(integer) 4
 
doitedu03:6379> PFMERGE HN HN:ZZ HN:CS
OK
doitedu03:6379> PFCOUNT HN
(integer) 6

找规律:
给定N个随机得整数,从右往左数0得个数记录最大的K值,找K和N得关系。
hash算法转换成16位的二进制
在这里插入图片描述

N(我一共去了几个数字) log2N K(最大的0的个数)
3400 11.73 11
3500 11.77 12
4000 11.97 12
4100 12.00 14
9100 13.15 13
9200 13.17 16
9700 13.24 12
9800 13.26 15
9900 13.27 13
10000 13.29 13

结论:数学结论N ≈ 2^k N是我一共传进去多少个数 K 是最后我数出来0的个数
如果N介于(2k,2k+1),用这种方式估值计算的值都等于2^k,显然误差比较大,所以用加权的方式来降低误差。
加权公式:
在这里插入图片描述

redis中的Hyperloglog

redis使用16384个分桶来实现HLL结构,使标准误差达到0.8125%。
redis使用的散列函数具有64位输出,这意味着它使用前14位来寻找“桶”,剩下的50位用于计算右边的0的数量。正如我们之前看到的,每个存储子集将存储最大的“连0数”,最大可能为50(因为散列中只有50个剩余位可以是0),每个存储子集需要6位才能能够存储最多50个(二进制为110010)。因此我们得到98304个bit来存储1个HLL结构;如果我们将这些bit转换为byte,我们得到6*16384/8 = 12288个byte(或12kb)这就是hyperloglog在redis实现占用的空间大小。

算法原理

Hyperloglog(HLL)是从Loglog算法派生的概率算法,用于确定非常大的集合的基数,而不需要存储其所有值。
正如之前所说,常规集合或位图可能非常耗费资源。HLL使用固定大小的结构来解决这个问题,根据实际使用情况,它可以低于16kb。作为低资源需求的代价,基数测量是概率性的,意味着具有小于2%的误差。也就是说:
假设我们有一个1000000个ID的集合,
2%的错误意味着有可能在计算基数时错过1000000个唯一身份用户,为20000
然后,我们可以得到以下两种最坏情况(1000000-20000)= 980.000 || (1000000 + 20000)= 1020000
看起来误差有点多,实际中大多数情况下HLL实现的错误率低于1%。而且由于存在错误率,所以使用HLL表示在其应用场景该误差是可以接受的。

基本原理

HLL的严格数学论证在这里不作解释,通俗来说HLL是通过散列中左边连续0的数量来估计给定集合的基数,因为一个好的哈希算法可以确保我们每个可能的散列具有大致相同的出现概率和均匀分布。这允许HLL算法基于具有最左边0的流的散列来估计它已经“看到”的元素的量。例如,假设我有一个哈希函数,给定一个元素它返回数字0-15的二进制表示:
在这里插入图片描述

其中二进制共有4位,每位出现0的概率是1/2,所以如果连续出现四个0则元素个数至少有16个,那么我如果得到一个左边有k个0元素则至少有2(k)个元素。
但是如果集合中只有一个元素,且元素每一位都是0怎么办,这时候就需要采用HLL中的分桶平均法了。分桶平均的基本原理是将统计数据划分为m个桶,每个桶分别统计各自的最大连续0个数并能得到各自的基数预估值 ,最终求其调和平均数即可,举个例子我们将集合划分为8个子集,那么需要将哈希值的前3位用于子集寻址,后几位从左边统计连续0的个数。
在这里插入图片描述
在这里插入图片描述
分段偏差修正
在HLLC的论文中,作者在实现建议部分还给出了在n相对于m较小或较大时的偏差修正方案。具体来说,设E为估计值:
当E <= 5m/2时,使用LC进行估计。
当 5m/2 < E <= 2(32)/30时,使用上面给出的HLC公式进行估计。
当 E > 2(32)/30时,估计公式如为
关于分段偏差修正效果分析也可以在算法原论文中找到。

严格的数学证明,需要用到伯努利分布,多重伯努利实验以及似然估计等数学知识;参考
https://www.cnblogs.com/linguanh/p/10460421.html
https://www.yuque.com/abser/aboutme/nfx0a4
https://zhuanlan.zhihu.com/p/77289303
https://zhuanlan.zhihu.com/p/26614750

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HyperLogLog数据结构 的相关文章

随机推荐

  • Java中对象比较的三种方式

    一 针对对象值是否相等的比较 和 equals 的区别 当我们提到比较值的时候 大多数人都会想到 因为在一般情况下 人们对于比较的概念中 数字比较的应用场景出现频率是最多的 首先我们创建一个类 之后新建这个类的对象来进行比较验证 class
  • DDR中的ZQ校准

    转载自https www xuebuyuan com 3233906 html What s the ZQ Calibration command it used to calibrate DRAM Ron ODT values In no
  • Maven程序 tomcat插件安装与web工程启动

    第一步 在mvnrepository库中找到tomcat插件 1 打开mvnrepository官网 搜索 tomcat maven 向下滑动找到 org apache tomcat maven 点进去 2 在这里点第一个 Apache T
  • 基于Matlab的随机森林算法实现(附算法介绍及代码详解)

    本算例完整代码领取方式在文末展示 一 内容提要 在地学领域中 岩性的准确识别对于储层评价来说至关重要 因此 今天笔者想要分享的是随机森林算法在岩性识别中的应用与代码实现 科普中国 科学百科定义 随机森林 Random forest 指的是利
  • 一文学会目前最火热的大数据技术

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由michelmu发表于云 社区专栏 Elasticsearch是当前主流的分布式大数据存储和搜索引擎 可以为用户提供强大的全文本检索能力 广泛应用于日志检索 全站搜索等领域 L
  • C程序运行步骤

    1 首先输入和编辑源程序 生成 c文件 2 对源程序进行编译 编译的作用首先是对源程序进行检查 判定他有无语法方面的错误 生成 obj文件 3 然后进行连接处理 把编译后的模块连接装配起来 再与函数库 例如scanf printf 连接成一
  • Web开发权威指南笔记(一)

    书 Web开发权威指南 美 Chris Aquino Todd Gandee著 为1st实战项目Ottergram练习以及代码整理 全为个人借鉴本书产出 若需要转载请联系通知我 谢谢 最终成果展示 第一章 配置开发环境 文档与参考资料 De
  • 手把手教你从零开发到上线一个答题微信小程序项目实战教程之01.开发环境搭建,微信小程序helloworld

    上线项目演示 微信搜索 放马来答 或扫以下二维码体验 项目大纲 1 开发环境搭建 微信小程序helloworld 2 题目分类页 3 答题页mock数据 4 答题页请求真实数据 pay 5 答题页记录错题 6 结果得分页 pay 7 展示错
  • springmvc url地址配置

    springmvc url地址配置 RequestMapping 注解的概念 通过 RequestMapping将请求地址与方法进行绑定 可以在类级别和方法级别声明 类级别的注解负责将一个特定的请求路径映射到一个控制器上 将url和类绑定
  • django-admin.py startproject HelloWorld创建文件提示invalid syntax

    直接用win R 输入cmd 输入python 然后输入django admin py startproject HelloWorld创建文件提示invalid syntax 解决方法 直接在cmd下执行语句 即可生成Helloworld项
  • MybatisPlus入门和分页和条件查询里面的条件和null值的处理方式和查询投影和查询条件设置和id生成相关和逻辑删除

    MybatisPlus 简化了mybatis之前的在springboot整合MyBatis时需要自己写sql语句在接口中 现在只需要让接口继承BaseMapper lt 实体类 gt 然后在测试类中接口 增删改查方法 即可 不用像sprin
  • MMEditing代码阅读笔记一:main()函数中的build_model()

    MMEditing代码阅读笔记一 main 函数中的build model 小白一枚 编程功底很弱 接触MMEditing这套代码 刚开始小眉头一皱 鼠标见点来点去不知道咋个回事 网上又没有关于MMEditing代码阅读的相关阐述 眉头更皱
  • LEFT JOIN右表为空也查出数据

    SELECT A B type FROM Table A A LEFT JOIN Table B B ON A id B id WHERE B type 1 改为 SELECT A B type FROM Table A A LEFT JO
  • 在WinForm中屏蔽中文输入法

    在WinForm的开发中 有时有些特殊的要求 例如 在某个Form上彻底屏蔽中文输入法 使之不能切换到中文输入 不能进行中文输入 这个问题看上去简单 实现起来并没有想象中的简单 下面 把我做的几个实验依次列举 就会发现 其实实现起来还是有一
  • websocket菜鸟教程(1.1)

    创建自己的websocket服务 先了解node js websocket 的基本使用https www npmjs com package nodejs websocket 第一步先安装 npm install nodejs websoc
  • mysql5.6安装步骤详细_详解MySQL5.6安装步骤

    是开放源码的小型关系型数据库管理系统 目前MySQL被广泛应用于在Internet上的中小型网站中 但是对于刚接触MySQL数据库服务器的朋友来说 是非常陌生的 那么现在爱站小编为大家详解MySQL5 6步骤 1 点击下载好的安装文件 出现
  • console控制台错误及处理过程

    1 ERROR Failed to execute goal org apache maven plugins maven compiler plugin 2 5 1 compile default compile on project l
  • 为什么组件中的data是一个函数而不是一个对象?

    JS中的对象是引用类型的数据 当多个实例引用同一个对象时 只要有一个实例对这个对象进行操作 其他实例中的数据也会发生变化 而在vue中 更想要每个组件都有自己的数据 不会互相干扰 所以组件的数据不能写成对象的形式而要是函数的形式 数据以函数
  • Ubuntu下非常给力的下载工具

    Windows下的下载工具 迅雷 之所以下载速度快 乃是它能搜索资源 为己所用 而不是仅仅从原始地址这单一资源处下载 Ubuntu下也有类似的工具 那就是aira2 aira2是一个命令行下载工具 可以配合其他图形界面的下载软件使用 我用的
  • HyperLogLog数据结构

    基数计数 cardinality counting 通常用来统计一个集合中不重复的元素个数 例如统计某个网站的UV 或者用户搜索网站的关键词数量 数据分析 网络监控及数据库优化等领域都会涉及到基数计数的需求 要实现基数计数 最简单的做法是记