简介: 本文将会介绍Hologres基于roaringbitmap实现超高基数的UV计算

RoaringBitmap是一种压缩位图索引,RoaringBitmap自身的数据压缩和去重特性十分适合对于大数据下uv计算。其主要原理如下:

  • 对于32bit数, RoaringBitmap会构造2^16个桶,对应32位数的高16位;32位数的低16位则映射到对应桶的一个bit上。单个桶的容量由桶中的已有的最大数值决定
  • bitmap把32位数用1位表示,可以大大地压缩数据大小。
  • bitmap位运算为去重提供了手段。

主体思想(T+1):把上一天的所有数据根据最大的查询维度聚合出的uid结果放入RoaringBitmap中,把RoaringBitmap和查询维度存放在聚合结果表(每天百万条)。之后查询时,利用Hologres强大的列存计算直接按照查询维度去查询聚合结果表,对其中关键的RoaringBitmap字段做or运算进行去重后并统计基数,即可得出对应用户数UV,count条数即可计算得出PV,达到亚秒级查询。

只需进行一次最细粒度的预聚合计算,也只生成一份最细粒度的预聚合结果表。得益于Hologres的实时计算能力,该方案下预计算所需的次数和空间都达到较低的开销。

Hologres计算UV、PV方案详情

图1 Hologres基于RoaringBitmap计算pv uv流程

1.创建相关基础表

1)使用RoaringBitmap前需要创建RoaringBitmap extention,语法如下,同时该功能需要Hologres  0.10版本。

CREATE EXTENSION IF NOT EXISTS roaringbitmap;

2)创建表ods_app为明细源表,存放用户每天大量的明细数据 (按天分区),其DDL如下:

BEGIN;
CREATE TABLE IF NOT EXISTS public.ods_app (uid text,country text,prov text,city text,channel text,operator text,brand text,ip text,click_time text,year text,month text,day text,ymd text NOT NULL
);
CALL set_table_property('public.ods_app', 'bitmap_columns', 'country,prov,city,channel,operator,brand,ip,click_time, year, month, day, ymd');
--distribution_key根据需求设置,根据该表的实时查询需求,从什么维度做分片能够取得较好效果即可
CALL set_table_property('public.ods_app', 'distribution_key', 'uid');
--用于做where过滤条件,包含完整年月日时间字段推荐设为clustering_key和event_time_column
CALL set_table_property('public.ods_app', 'clustering_key', 'ymd');
CALL set_table_property('public.ods_app', 'event_time_column', 'ymd');
CALL set_table_property('public.ods_app', 'orientation', 'column');
COMMIT;

3)创建表uid_mapping为uid映射表,uid映射表用于映射uid到32位int类型。

RoaringBitmap类型要求用户ID必须是32位int类型且越稠密越好(用户ID最好连续),而常见的业务系统或者埋点中的用户ID很多是字符串类型,因此使用uid_mapping类型构建一张映射表。映射表利用Hologres的SERIAL类型(自增的32位int)来实现用户映射的自动管理和稳定映射。

注: 该表在本例每天批量写入场景,可为行存表也可为列存表,没有太大区别。如需要做实时数据(例如和Flink联用),需要是行存表,以提高Flink维表实时JOIN的QPS。

BEGIN;CREATE TABLE public.uid_mapping (uid text NOT NULL,uid_int32 serial,PRIMARY KEY (uid) );--将uid设为clustering_key和distribution_key便于快速查找其对应的int32值
CALL set_table_property('public.uid_mapping', 'clustering_key', 'uid');
CALL set_table_property('public.uid_mapping', 'distribution_key', 'uid');
CALL set_table_property('public.uid_mapping', 'orientation', 'row');
COMMIT;

3)创建表dws_app基础聚合表,用于存放在基础维度上聚合后的结果

基础维度为之后进行查询计算pv和uv的最细维度,这里以country, prov, city为例构建聚合表

begin;
create table dws_app(country text,prov text,city text, ymd text NOT NULL,  --日期字段uid32_bitmap roaringbitmap, -- UV计算pv integer, -- PV计算primary key(country, prov, city, ymd)--查询维度和时间作为主键,防止重复插入数据
);
CALL set_table_property('public.dws_app', 'orientation', 'column');
--clustering_key和event_time_column设为日期字段,便于过滤
CALL set_table_property('public.dws_app', 'clustering_key', 'ymd');
CALL set_table_property('public.dws_app', 'event_time_column', 'ymd');
--distribution_key设为group by字段
CALL set_table_property('public.dws_app', 'distribution_key', 'country,prov,city');
end;

2.更新dws表及id_mapping表

每天从上一天的uid中找出新客户(uid映射表uid_mapping中没有的uid)插入到uid映射表中

WITH
-- 其中ymd = '20210329'表示上一天的数据user_ids AS ( SELECT uid FROM ods_app WHERE ymd = '20210329' GROUP BY uid ),new_ids AS ( SELECT user_ids.uid FROM user_ids LEFT JOIN uid_mapping ON (user_ids.uid = uid_mapping.uid) WHERE uid_mapping.uid IS NULL )
INSERT INTO uid_mapping SELECT  new_ids.uid
FROM    new_ids
;

更新完uid映射表后,将数据做聚合运算后插入聚合结果表,主要步骤如下:

  • 首先通过源表inner join uid映射表,得到上一天的聚合条件和对应的uid_int32;
  • 然后按照聚合条件做聚合运算后插入RoaringBitmap聚合结果表,作为上一天的聚合结果;
  • 每天只需进行一次聚合,存放一份数据,数据条数最坏等于UV的量。以案例说明,明细表每天几亿的增量,在聚合结果表每天只需存放百万级数据。
WITHaggregation_src AS( SELECT country, prov, city, uid_int32 FROM ods_app INNER JOIN uid_mapping ON ods_app.uid = uid_mapping.uid WHERE ods_app.ymd = '20210329' )
INSERT INTO dws_app SELECT  country,prov,city,'20210329',RB_BUILD_AGG(uid_int32),COUNT(1)
FROM    aggregation_src
GROUP BY country,prov,city
;

3.UV、PV查询

查询时,从汇总表dws_app 中按照查询维度做聚合计算,查询bitmap基数,得出Group by条件下的用户数

--运行下面RB_AGG运算查询,可先关闭三阶段聚合开关性能更佳(默认关闭)
set hg_experimental_enable_force_three_stage_agg=off    --可以查询基础维度任意组合,任意时间段的uv pv
SELECT  country,prov,city,RB_CARDINALITY(RB_OR_AGG(uid32_bitmap)) AS uv,sum(1) AS pv
FROM    dws_app
WHERE   ymd = '20210329'
GROUP BY country,prov,city;--查一个月
SELECT  country,prov,RB_CARDINALITY(RB_OR_AGG(uid32_bitmap)) AS uv,sum(1) AS pv
FROM    dws_app
WHERE   ymd >= '20210301' and ymd <= '20210331'
GROUP BY country,prov;
该查询等价于
SELECT  country,prov,city,COUNT(DISTINCT uid) AS uv,COUNT(1) AS pv
FROM    ods_app
WHERE   ymd = '20210329'
GROUP BY country,prov,city;SELECT  country,prov,COUNT(DISTINCT uid) AS uv,COUNT(1) AS pv
FROM    ods_app
WHERE   ymd >= '20210301' and ymd <= '20210331'
GROUP BY country,prov;         

4.可视化展示

计算出UV、PV和,大多数情况需要用BI工具以更直观的方式可视化展示,由于需要使用RB_CARDINALITY 和 RB_OR_AGG 进行聚合计算,需要使用BI的自定义聚合函数的能力,常见的具备该能力的BI包括Apache Superset和Tableau,下面将会讲述这两个BI工具的最佳实践。

4.1 使用 Apache Superset

Apache Superset 对接 Hologres 的方式,请参考产品手册。在Superset中可以直接使用dws_app表作为Dataset使用

并且在数据集中,创建一个单独Metrics,名为UV,表达式如下:

RB_CARDINALITY(RB_OR_AGG(uid32_bitmap))

然后您就可以开始探索数据了

当然也可以创建Dashborad:

4.2 使用 Tableau

Tableau 对接 Hologres 的方式,请参考产品手册。可以使用Tableau的直通函数直接实现自定义函数的能力,详细介绍请参照Tableau的手册。在Tableau对接Hologres后,可以创建一个计算字段,表达式如下

RAWSQLAGG_INT("RB_CARDINALITY(RB_OR_AGG(%1))", [Uid32 Bitmap])

然后您就可以开始探索数据了

当然也可以创建Dashborad

原文链接

本文为阿里云原创内容,未经允许不得转载。

Hologres如何支持超高基数UV计算(基于roaringbitmap实现)相关推荐

  1. Hologres如何基于roaringbitmap实现超高基数UV计算?

    简介:本文将会介绍Hologres基于roaringbitmap实现超高基数的UV计算 RoaringBitmap是一种压缩位图索引,RoaringBitmap自身的数据压缩和去重特性十分适合对于大数 ...

  2. Flink+Hologres亿级用户实时UV精确去重最佳实践

    简介:Flink+Hologres亿级用户实时UV精确去重最佳实践 UV.PV计算,因为业务需求不同,通常会分为两种场景: 离线计算场景:以T+1为主,计算历史数据 实时计算场景:实时计算日常新增的数 ...

  3. Hologres揭秘:如何支持超高QPS在线服务(点查)场景

    简介:本期我们将揭秘Hologres如何支持超高QPS在线服务(点查)场景. Hologres(中文名交互式分析)是阿里云自研的一站式实时数仓,这个云原生系统融合了实时服务和分析大数据的场景,全面兼容 ...

  4. Hologres如何支持亿级用户UV计算

    简介: 本文将介绍阿里云Hologres如何基于RoaringBitmap进行UV等高复杂度计算的方案,实现亿级用户万级标签亚秒级分析,帮助用户从Kylin平滑迁移到Hologres,实现更实时.开发 ...

  5. 阿里巴巴宣布架构调整;英伟达放大招!重磅发布 ​TensorRT 7 ,支持超千种计算变换;苹果、谷歌和亚马逊罕见结盟……...

    戳蓝字"CSDN云计算"关注我们哦!  嗨,大家好,重磅君带来的[云重磅]特别栏目,如期而至,每周五第一时间为大家带来重磅新闻.把握技术风向标,了解行业应用与实践,就交给我重磅君吧 ...

  6. 【kafka】支持超高并发的kafka网络设计

    1.概述 [源码请入群]41. 响应消息是如何发送给客户端的 视频地址:https://www.bilibili.com/video/BV1M64y1D7NN?p=41 [源码请入群]42. 支持超高 ...

  7. 关于风向的u、v分量,及根据uv计算风向公式

    风向是按正北方向起算的,0度表示北风.90度表示东风. u表示经度方向上的风,v表示纬度方向上的风. u为正,表示西风,从西边吹来的风.v为正,表示南风,从南边从来的风.假如u为1,v为1,则表示西南 ...

  8. 零维水温模型计算——基于matlab建立计算模型

    零维水温模型计算--基于matlab建立计算模型 零维水温模型 基本方程 计算参数准备 matlab模型的建立 四阶龙格-库塔法的matlab实现 水面的净流通量φ~s~的计算函数 湖水与岩土的换热φ ...

  9. 阿里云数据库产品HybridDB简介——OLAP数据库,支持行列混合存储,基于数据库Greenplum的开源版本,并且吸收PostgreSQL精髓...

    为什么会有HybridDB的诞生?它经历了怎样的研发历程?它的应用场景和情况是怎样的?带着这些问题,InfoQ对阿里云的数据库专家兼Postgres中国社区/中国用户会主席萧少聪先生进行了采访,以下文 ...

最新文章

  1. Ubuntu下Nginx/PHP/MYSQL开发环境的配置方法
  2. php 接口 2.0,YII 2.0 API接口开发
  3. SM4密码算法(附源码)
  4. 广告计算——平滑CTR
  5. 判断是否是ie浏览器 前端js_JS判断是否是IE浏览器
  6. jeecg如何控制用户权限_如何为用户定制个性化控制台?
  7. 如何编写兼容各主流邮箱的HTML邮件并发送
  8. Python模拟Linux的Crontab, 写个任务计划需求
  9. away3d 4.0.9Gold 学习笔记 加载方法总结(4)
  10. 如何做一个国产数据库(四)
  11. Flask实现发送邮件功能
  12. redhat linux 7 ntp,技术|RHCE 系列(十):在 RHEL/CentOS 7 中设置 NTP(网络时间协议)服务器...
  13. python的书写格式_python 快速写作技巧,格式
  14. Deep Graph Library消息传递机制-Message Passing详解
  15. 偶遇的webshell,那得冲一波
  16. Vue子组件与父组件(看了就会)
  17. matlab地震p波,如何确定地震深度?试试远震P波
  18. 远程文件包含 php,php本地及远程文件包含漏洞
  19. 几万年前,有一只猴子大闹地府后删库跑路
  20. 美国高考能不能带计算机,这件“神器”在美国被高中允许却被美国大学禁止

热门文章

  1. vue修改计算属性的值_Vue语法高级之计算属性和侦听器
  2. 数据查询和业务流分开_TiDB HTAP 助力小红书业务升级
  3. Event用计算机语言,求高人解释下一段计算机语言。
  4. Linux上的JAVA的IDE,在linux上运行的基于文本的强大java IDE
  5. 模拟进程创建、终止、阻塞、唤醒原语_操作系统第二章--进程的描述与控制
  6. 一行代码蒸发64亿人民币!黑客盯上区块链漏洞!Python真的变态!
  7. python教程苹果版_python教程
  8. 易语言单窗口单ip软件源码_梦幻西游怎样多开ip转金?十大攻略秘籍速来看
  9. linux某个线程信号唤醒,linux多线程编程--信号量和条件变量 唤醒丢失事件
  10. 计算机四级软件工程知识点,计算机四级考试题库及搜题软件,送一份备考指南给大家!...