一、背景

  1. 什么是留存 比如用户今天使用某应用,明天还继续使用该应用,叫做留存。

  2. bitmap原理 基本思想是用数组下标表示元素的值,用0,1标记元素是否存在,1表示存在,0表示不存在。由于使用bit为单位来存储数据,大大节省了存储空间。例如:给定一个数组array=[1,3,5];

  1. 为什么要用bitmap?bitmap为什么能计算留存?bitmap为什么只支持int类型?

  • ①节省存储空间。

  • ②留存实际上是求交集,bit可以进行与运算。bitmap不仅仅可以计算留存,还可以计算漏斗、新增、活跃,灵活使用bitmap的交并差集。

  • ③数组下标代表的是元素的值。

二、函数

  1. bitmap_hash():对任意非整型的输入计算32位的哈希值,返回包含该hash值的bitmap。

  2. to_bitmap():bigint转换为bitmap,输出包含该元素的bitmap。

  3. bitmap_intersect(bitmap):输入一组bitmap,求交集并返回一个新的bitmap。

  4. bitmap_union(bitmap):输入一组bitmap,求并集,并返回新的bitmap。

  5. bitmap_count():返回count值。

  6. intersect_count(expr1,expr2,expr3):求交集。expr1是 求交集Bitmap 列,expr2是用来过滤的维度列, expr3开始是变长参数,含义是过滤维度列的不同取值。

  7. bitmap_and(bitmap expr1,bitmap expr2):计算两个bitmap的交集,返回新的bitmap。

  8. hll_hash():任意类型转换hll类型。

  9. hll_union_agg(hll):计算count distinct。

三、count distinct 与bitmap精确去重

-- 1.传统count distinct
-- 40475
selectcount(distinct user_id),bitmap_count(bitmap_union(to_bitmap(user_id))),BITMAP_UNION_COUNT(to_bitmap(user_id))
from gx_doris_game_login_day_agg
where actday ='2020-10-02'
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'-- 2.bitmap精确去重
-- 40475
selectbitmap_count(user_id)
from gx_doris_game_login_day_agg_bitmap
where actday in ('2020-10-02')
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'

四、留存计算方法

  1. count distinct 传统的count distinct精确去重可以保留明细数据,灵活性较高,但是Doris是基于MPP架构,在计算过程中需要多次进行数据shuffle,性能会随着数据量增大而下降。

SELECTa.actday,count(distinct a.user_id) as active,count(distinct case when datediff(b.actday,a.actday)=1 then b.user_id end) as retention,count(distinct case when datediff(b.actday,a.actday)=2 then b.user_id end) as retention2
from
(selectactday,user_id,appkeyfrom gx_doris_game_login_day_aggwhere actday ='2020-10-02'and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
)a
left join
(selectactday,user_id,appkeyfrom gx_doris_game_login_day_aggwhere actday in ('2020-10-03','2020-10-04')and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
)b on a.user_id=b.user_id
group by a.actday
  1. bitmap 假如给定一个数组A, 对该数组去重, 初始化bitmap为全0; 逐个处理数组A的元素, 以A中元素取值作为bitmap的下标, 将该下标的bit置1; 最后统计bitmap中1的个数即为数组A的count distinct结果。

-- int类型
select'2020-10-02' actday,intersect_count(to_bitmap(user_id),actday,'2020-10-02') as active,-- intersect_count(to_bitmap(user_id),actday,'2020-10-03') as user03,intersect_count(to_bitmap(user_id),actday,'2020-10-02','2020-10-03') as retention1,intersect_count(to_bitmap(user_id),actday,'2020-10-02','2020-10-04') as retention2
from gx_doris_game_login_day_agg_1
where actday in ('2020-10-02','2020-10-03','2020-10-04')
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
-- string类型:user_id
-- 40475 32476 31688
-- 0.375s
select'2020-10-02' actday,intersect_count(bitmap_hash(user_id),actday,'2020-10-02') as active,-- intersect_count(to_bitmap(user_id),actday,'2020-10-03') as user03,intersect_count(bitmap_hash(user_id),actday,'2020-10-02','2020-10-03') as retention1,intersect_count(bitmap_hash(user_id),actday,'2020-10-02','2020-10-04') as retention2
from gx_doris_game_login_day_agg
where actday in ('2020-10-02','2020-10-03','2020-10-04')
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
-- string类型:m1
-- 2020-10-02 16907 12502 11611
-- 0.288s
select'2020-10-02' actday,intersect_count(bitmap_hash(m1),actday,'2020-10-02') as active,-- intersect_count(to_bitmap(m1),actday,'2020-10-03') as user03,intersect_count(bitmap_hash(m1),actday,'2020-10-02','2020-10-03') as retention1,intersect_count(bitmap_hash(m1),actday,'2020-10-02','2020-10-04') as retention2
from gx_doris_game_login_day_agg
where actday in ('2020-10-02','2020-10-03','2020-10-04')
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
-- bitmap类型1
-- 2020-10-02 40475 32476 31688
-- 0.054s
select'2020-10-02' actday,intersect_count(user_id,actday,'2020-10-02') as active,intersect_count(user_id,actday,'2020-10-02','2020-10-03') as retention1,intersect_count(user_id,actday,'2020-10-02','2020-10-04') as retention2
from gx_doris_game_login_day_agg_bitmap
where actday in ('2020-10-02','2020-10-03','2020-10-04')
and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
-- bitmap类型2
-- 32476
SELECTbitmap_count(bitmap_intersect(user_id)) as retention1
from
(SELECTactday,bitmap_union(user_id) user_idfrom gx_doris_game_login_day_agg_bitmapwhere actday in ('2020-10-02','2020-10-03')and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'group by actday
)a
-- bitmap类型3
-- 40475 32476 31688
selectbitmap_count(user01) as active,bitmap_count(bitmap_and(user01,user02)) as retention1,bitmap_count(bitmap_and(user01,user03)) as retention2
from
(selectbitmap_union(case when actday='2020-10-02' then user_id end)  as user01,bitmap_union(case when actday='2020-10-03' then user_id end)  as user02,bitmap_union(case when actday='2020-10-04' then user_id end)  as user03from gx_doris_game_login_day_agg_bitmapwhere actday in ('2020-10-02','2020-10-03','2020-10-04')and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
)a
  1. HLL

-- hll近似去重
-- 基本思想:a集合 + b集合 -(a ∪ b)= a ∩ b
-- hll  10543
SELECTa+b-c as retention1
from
(selecthll_union_agg(case when actday='2020-10-02' then HLL_HASH(user_id) end) as a,hll_union_agg(case when actday='2020-10-03' then HLL_HASH(user_id) end) as b,hll_union_agg(case when actday in ('2020-10-02','2020-10-03') then HLL_HASH(user_id) end) as cfrom gx_doris_game_login_day_agg_1where actday in ('2020-10-02','2020-10-03')and appkey='mg_un_d2669937895c912d368426d84d1d8fd2'
)t

四、总结

如果数据集的基数在百万、千万量级,使用 count distinct 即可;如果基数在亿级以上,并且需要精确去重,用Bitmap类型;如果可以接受近似去重,可以使用HLL类型。

原文链接:https://blog.csdn.net/weixin_43433596/article/details/119148601

作者:csdn、ベ斑驳

Doris bitmap实现留存计算相关推荐

  1. 【Android 内存优化】Bitmap 内存占用计算 ( Bitmap 图片内存占用分析 | Bitmap 内存占用计算 | Bitmap 不同像素密度间的转换 )

    文章目录 一.Bitmap 内存占用 二.Bitmap 内存占用计算示例 三.Bitmap 内存占用与像素密度 四.Bitmap 内存占用与像素密度示例 一.Bitmap 内存占用 在 Android ...

  2. android图片适配(图片大小与屏幕密度)Bitmap占用内存计算

    目录 概述 dpi 计算公式 dp与px换算公式: android系统适配图片规律: 同名图片放在不同密度的文件夹下,系统选择图片规律 同一张图片,放在不同密度的Drawable文件夹下,ImageV ...

  3. Android—Bitmap图片大小计算、压缩与三级缓存

    Bitmap对象占用内存大小: bitmap.getByteCount() 图片所占内存大小计算方式:图片长度 x 图片宽度 x 一个像素点占用的字节数. Android Bitmap使用的三种颜色格 ...

  4. android bitmap大小计算,android 之Bitmap 内存大小计算

    QQ截图20180426154121.png 想要知道一个Bitmap 占用多大内存 我们只需要调用getByteCount方法就可以了,但是不可能每次都将图片塞到项目中然后把运行看吧,所以我们必须要 ...

  5. 2021_lg_03.SQL实战:如何用sql计算用户留存问题

    如何用sql计算用户留存问题 一.留存 1 .留存的含义: 留存:指基准日到APP的用户在之后的n日当天返回APP的人数: 留存率 = 基准日之后的n天当日返回的用户数 / 基准日的用户数 * 100 ...

  6. php计算用户留存,利用Python计算新增用户留存率

    原始数据:创角日志和登录日志 导入需要的库 pandas import pandas as pd 1.获取数据 #读取创角日志 df_create = pd.read_csv(r'F:\Python\ ...

  7. 一种计算用户留存的方法

    0x00 概述 用户留存分析是互联网时代常用的一种数据分析方法.而很多快速发展的公司并没有相应的方法论沉淀,这就导致了在计算用户留存的时候会出现下面的一些问题:1)用户留存的定义不明确,不同的研发有自 ...

  8. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践

    导读: 随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时 OLAP 数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高 ...

  9. 叮咚买菜基于Doris引擎的应用实践

    全网最全大数据面试提升手册! 叮咚买菜创立于 2017 年 5 月,是一家专注美好食物的创业公司.叮咚买菜专注吃的事业,为满足更多人"想吃什么"而努力,通过美好食材的供应.美好滋味 ...

最新文章

  1. jQuery_第五章_jQuery事件和动画
  2. 积跬步,聚小流-------一个登录中的知识点
  3. easyui关机图标_如何在Windows 10中创建关机图标
  4. 数据结构基础学习之(串与数组)
  5. 安装CentOS 6/7
  6. python从入门到放弃百度云-Python从入门到放弃:概论
  7. Git:checkout命令无法切换回master
  8. SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 及动态查询中的标识符函数QUOTENAME
  9. 特朗普“能源独立”政策效果存疑
  10. linux下oracle 9204 soft only,在CentOS4.3(x86_64)上安装Oracle9204 for linux(x86_64)
  11. java 参考期刊文章_计算机论文java参考文献_期刊[J]_学位论文[D]_专著[M]_(30)
  12. python整蛊代码+详解
  13. Python使用struct处理二进制(pack和unpack用法)
  14. 交互式电子白板android,交互式电子白板教学应用
  15. kubernet-- windows之kubectl的安装及使用(巧克力)
  16. 记一次Java开发实习生的面试(糟糕)
  17. 提高影响力:职权+威信
  18. Apache Spark处理大数据入门,看这一篇就够了
  19. QMS-云质说质量 - 3 来料检验的九大坑,你踩过几个?
  20. 获取当前时间戳减去昨天的时间戳

热门文章

  1. haroopad编辑html,走进MARKDOWN的世界
  2. 安装openvpn出现这个问题,请问怎么解决呢
  3. ftp服务器上 批量移动文件路径,ftp服务器上 批量移动文件
  4. [Python]简单几行代码带你完成Python切换代理IP
  5. 计算机二级学校会设考点吗,2020年9月北京计算机二级考试考点设置
  6. 轻松学会python的turtle模块,画一箭穿心、小人儿发射爱心、520表白完整代码,海龟作图小创意
  7. 通过ajv.js对JSON数据格式进行校验
  8. Python递归及递归遍历目录
  9. 模拟hibernate的注解来创建数据表,内置注解
  10. 在线投票系统的设计与实现