更多精彩内容:请登录:ke.sandata.com.cn

前言

HLL是 HyperLogLog数据结构的简称。PostgresSQL通过插件的方式引入了这种新的数据类型hll。HyperLogLog是一个具有固定大小,类似于集合结构,用于可调精度的不同值计数。例如,在1280字节的hll数据结构中,它可以在很小的误差范围内估算出数百亿的不同值计数。

算法

hll可以被视为层次结构的不同集合/不同值计数算法的组合,并向上移动该层次结构的规则。为了区分上述描述算法,将其命名为以下:

♠ EMPTY

表示空集的常量值

♠ EXPLICIT

集合中确定的,唯一的,排序完整的整数列表,该列表保持一个固定的基数

♠ SPARSE

HyperLogLog是基于映射的“惰性”实现,是一种基于概率集合的数据结构。仅将非零寄存器的索引和值存储在 map中,直到非零寄存器的数量超过固定的基数。

♠ FULL

HyperLogLog是一个完全物化,基于列表的实现。它将每个寄存器的值显式存储在按寄存器索引排序的列表中。

基本概念

  • 基数计数

用来统计一个集合中不重复的元素的个数。

  • 基数计数实现

假设一个集合为Su,用列举法表示{2,3,1,4,5,9},如果此时有一个新的元素Xi=3要加入到集合Su中。如果Su中包含该元素,那么该元素将不会被加入到集合Su中,否则,加入该元素到集合中,计数值为Su,即基数值为元素的中非相同值的个数。如集合中{1,2,3,5,2},基数为4,因为2是 DV(Distinct Value),不被计算到基数中。

该实现有两个问题:

  1. 当集合无限增加,元素增多时,相应的存储内存也会无限增长
  2. 当集合无线增加,元素增多,判断是否包含待加入元素的成本也将增加。

实现动机

最初扩充原始HLL算法如下:

  • 一般情况下,一个HLL占用 regwidth * 2^log2m 位存储。
  • 典型使用中,log2m = 11 和 regwidth = 5时,将请求需要10240位或者1280个字节。即 5 * 2^11 = 5* 2048 = 10240
  • 还有一种就是有很多的字节

最初的HLL算法的第一个补充来自于实现1280个字节需要160个64位整数的大小。因此,如果希望在低基数下获得更高的准确性,则可以将一组明确的输入保留为64位整数的排序列表,直到达到第161个不同的值为止。这将为提供流中不同值的真实表示,同时需要相同数量的内存。 (这是EXPLICIT算法)。

第二个是不需要存储值为零的寄存器。可以简单地将一组具有非零值的寄存器表示为从索引到值的映射。该映射存储为索引值对的列表,这些索引值对是长度为log2m + regwidth的bit-packed的“short words”。 (这是SPARSE算法。)

结合这两种增强,得到了一个“promotion hierarchy”,可以对算法进行调整以提高准确性,内存或性能。

初始化和存储新的hll对象将仅分配一个小的小标记值,该值表示空集(EMPTY)。当添加前几个值时,唯一整数的排序列表存储在EXPLICIT集中。当希望停止权衡内存的准确性时,已排序列表中的值将“promoted”为基于SPARSE映射的HyperLogLog结构。最后,当有足够的寄存器时,基于映射的HLL将转换为位打包的FULL HLL结构。

自然地,EMPTY和EXPLICIT表示的基数估计是准确的,而SPARSE和FULL表示的准确性受原始HLL算法提供的保证的约束。

安装和使用HLL

解压安装包

[postgres@pgserver plugin]$ ls
postgresql-hll-2.15.1  postgresql-hll-2.15.1.tar.gz
[postgres@pgserver plugin]$ cd postgresql-hll-2.15.1
[postgres@pgserver postgresql-hll-2.15.1]$ ls
CHANGELOG.md  expected     include  Makefile   REFERENCE.md  src
DEVELOPER.md  hll.control  LICENSE  README.md  sql           update

编译安装

[postgres@pgserver postgresql-hll-2.15.1]$ make -j24 && make install

测试

[postgres@pgserver postgresql-hll-2.15.1]$ psql -d postgres
psql (13.2)
Type "help" for help.postgres=# CREATE EXTENSION hll;
CREATE EXTENSION
postgres=#

构建数据

CREATE TABLE helloworld(id integer,set hll)
;
--- Insert an empty HLL
INSERT INTO helloworld(id,set)VALUES(1,hll_empty())
;--- Add a hashed integer to the HLL
UPDATEhelloworld
SET
set = hll_add(set, hll_hash_integer(12345))
WHEREid = 1
;--- Or add a hashed string to the HLL
UPDATEhelloworld
SET
set = hll_add(set, hll_hash_text('hello world'))
WHEREid = 1
;--- Get the cardinality of the HLL
SELECThll_cardinality(set)
FROMhelloworld
WHEREid = 1
;
postgres=# SELECT
postgres-#   hll_cardinality(set)
postgres-# FROM
postgres-#   helloworld
postgres-# WHERE
postgres-#   id = 1
postgres-# ;hll_cardinality
-----------------2
(1 row)postgres=# SELECT * FROM helloworld ;id |                   set
----+------------------------------------------1 | \x128b7faaebcf97601e5541533f6046eb7f610e

从上面的示例中得到,首先构建了一个空的hll集合,然后向该集合中添加了两个值,那么得到的该hll的基数计数就是2。

接下来看一个更加实用的用例:

创建网站访问事实表和用户日访问表

CREATE TABLE facts (date            date,user_id         integer,activity_type   smallint,referrer        varchar(255)
);CREATE TABLE daily_uniques (date            date UNIQUE,users           hll
);

然后给网站访问表中插入过去1000天的访问数据(此处由于没有实际的数据,只能模拟过去1000天的数据)

[postgres@pgserver ~]$ psql -d postgres -f ~/test.sql

查看表

postgres=# SELECT count(*) FROM facts ;count
----------500000005000万数据

然后根据日期,对user_id进行hash处理,聚合每天用户访问网站的数据到 hll结构中。

INSERT INTO daily_uniques(date, users)SELECT date, hll_add_agg(hll_hash_integer(user_id))FROM factsGROUP BY 1;

查看表数据

postgres=# SELECT count(*) FROM daily_uniques ;count
-------1000
(1 row)只有1000行数据

现在查找一下每天hll的基数计数值

postgres=# SELECT date, hll_cardinality(users) FROM daily_uniques LIMIT 10;date    |  hll_cardinality
------------+-------------------2021-02-06 | 9725.8527337070772021-02-21 | 9725.8527337070772021-02-02 | 9725.8527337070772021-02-08 | 9725.8527337070772021-02-10 | 9725.8527337070772021-02-03 | 9725.8527337070772021-02-14 | 9725.8527337070772021-02-22 | 9725.8527337070772021-02-11 | 9725.8527337070772021-02-20 | 9725.852733707077

此刻,可能会想,可以用 COUNT DISTINCT做到基数统计。但是这里只能看到每天多少个唯一身份的用户访问了网站。

倘若想要查看每一周的唯一值呢?

HLL可以这样处理

postgres=# SELECT hll_cardinality(hll_union_agg(users)) FROM daily_uniques WHERE date >= '2018-10-02'::date AND date <= '2018-10-08'::date;hll_cardinality
-------------------9725.852733707077
(1 row)

或者查看一年中的每个月访问情况

postgres=# SELECT EXTRACT(MONTH FROM date) AS month, hll_cardinality(hll_union_agg(users))
postgres-# FROM daily_uniques
postgres-# WHERE date >= '2019-01-01' AND
postgres-#       date <  '2020-01-01'
postgres-# GROUP BY 1;month |  hll_cardinality
-------+-------------------3 | 9725.8527337070777 | 9725.8527337070778 | 9725.85273370707712 | 9725.8527337070775 | 9725.85273370707710 | 9725.85273370707711 | 9725.8527337070779 | 9725.8527337070774 | 9725.8527337070771 | 9725.8527337070772 | 9725.8527337070776 | 9725.852733707077

等等。因此,可以得到hll可以很好的来计算DV值,并且很快。

关于更多内容,大家可以去访问github网站来获取。

PostgreSQL HLL插件介绍—晟数学院相关推荐

  1. java postgresql插件_PostgreSQL HLL插件介绍

    前言 HLL是 HyperLogLog数据结构的简称.PostgresSQL通过插件的方式引入了这种新的数据类型hll.HyperLogLog是一个具有固定大小,类似于集合结构,用于可调精度的不同值计 ...

  2. 晟数学院 oracle,Oracle 控制文件存储解析

    控制文件块内容分布 SQL> SELECT TYPE, 1 RECORD_SIZE, 2 RECORDS_TOTAL, 3 RECORD_SIZE*RECORDS_TOTAL, 4 ceil(r ...

  3. 中文版orgin图像数字化工具_Origin数字化(Digitize)插件介绍(提取图片或扫描格式图形数据点)...

    数字化(Digitize)插件介绍 数宇化插件为origin网站提供的极为有用的免费插件之一,该插件可将普通曲线图直接在origin中数字化.例如,以通过扫描仪将曲线图扫入计算机, 或在网上获取的电子 ...

  4. postgresql|数据库|插件学习(一)---postgresql-12的内置插件pg_stat_statements的启用和使用

    前言:         插件就是原软件的扩展功能.postgresql有非常多的各种各样的插件,当然了,插件不安装对于我们使用数据库并没有什么太多的影响,可能只是不舒服一些而已,但有一些插件我们如果有 ...

  5. android浏览器插件介绍

    一 浏览器插件介绍:    1.1 概述 浏览插件本质是一个功能模块,是浏览器功能的一种扩充.其载体是dll或则so文件.它依附浏览器完成某一特定的功能.插件需要实现浏览器规定的一些函数,这些函数叫N ...

  6. gulp plugins 插件介绍

    原文:http://ju.outofmemory.cn/entry/103253 鸟窝 2014-11-28 3020 阅读 gulp Gulp是一个构建工具, 功能类似grunt, 以及Java生态 ...

  7. Maven实战——常用Maven插件介绍

    http://www.infoq.com/cn/news/2011/04/xxb-maven-7-plugin 我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任 ...

  8. Jquery提交表单 Form.js官方插件介绍

    來源:http://hi.baidu.com/dereky/blog/item/f9e8ab64c52f4ff3f736540c.html [JQuery框架应用]:form.js官方插件介绍 For ...

  9. 常用Maven插件介绍(下)(转)

    我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...

最新文章

  1. UVA 10494 - If We Were a Child Again(高精度除法和取余)
  2. 基于HTML5的3D网络拓扑树呈现
  3. 从AX4.0本地化SP2凭证系统的一个bug看UserConnection的使用
  4. c++ 一个函数包括多个返回值判断_轻松玩转函数式编程
  5. 验证多个Filter过滤一个资源时执行顺序
  6. aelf帮助C#工程师10分钟零门槛搭建DAPP私有链开发环境
  7. servlet文件上传下载_Servlet上传文件和下载文件示例
  8. C/C++ OpenCV之Scharr边缘检测
  9. 前端 优化 json stringify 在IE浏览器的兼容性 按钮点击不生效
  10. JavaScript获取图片的原始尺寸
  11. NAnt 与 MS Build
  12. SCPPO(十二):SQL误操作如何恢复?
  13. 计算机毕业设计:java基于SSM的班级管理系统
  14. linux启动盘制作
  15. 【开源】前端拖拽表单设计器 自定义表单
  16. 【java支付一 】java整合银联支付
  17. 将word文档锁定其他用户不可编辑
  18. WordPress付费资源素材下载主题 总裁CeoMax主题
  19. linux卸载小企鹅输入法,linux下小企鹅输入法的安装
  20. 基于Apriori算法的高职大学生就业能力的研究

热门文章

  1. 台式电脑 在哪找到计算机名,台式电脑内存条在哪个位置?帮你找到电脑内存条位置...
  2. 【《春娇与志明》:贱也要在一起 】-百度影集http://www.baidumovies.com
  3. linux下软件安装卸载
  4. OpenStack 网络项目(Neutron)的历史、现状与未来
  5. 基于Android驾校驾考助手 java驾照考试系统
  6. 服务器解压文件出错,压缩包解压错误我的电脑上,所以的压缩包解压时都会出错:1:在别的 爱问知识人...
  7. 带宽、中心频率、网速
  8. 用Python解决百钱买鸡问题
  9. GBase 8c V5 单机版安装示例
  10. 【振动幅值信号分析】Fluke 810测振仪、您贴身的振动诊断专家