网易首页 > 网易号 > 正文 申请入驻

去重Cube计算优化新思路

0
分享至

阿里妹导读

本文主要分享了作者在蚂蚁集团高管数据链路改造升级过程中,针对去重Cube的优化实践。

引言

SQL作为目前最通用的数据库查询语言,其功能和特性复杂度远不止大家常用的“SELECT * FROM tbl”这样简单,一段好的SQL和差的SQL,其性能可能有几十乃至上千倍的差距。而写出一个好的能兼顾性能和易用性的SQL,考验的不仅仅是了解到多少新特性新写法,而是要深入理解数据的处理过程,然后设计好数据的处理过程。

一、场景描述

在做数据汇总计算和统计分析时,最头疼的就是去重类指标计算(比如用户数、商家数等),尤其还要带多种维度的下钻分析,由于其不可累加的特性,几乎每换一种统计维度组合,都得重新计算。数据量小时可以暴力的用明细数据直接即时统计,但当数据量大时就不得不考虑提前进行计算了。

典型场景如下:省、市、区等维度下的支付宝客户端的日支付用户数(其中省、市、区为用户支付时所在的位置,表格中指标数据均为虚构的)。

存在一个情况,某用户早上在杭州市使用支付宝支付了一次,下午跑到绍兴市时又使用支付宝线下支付了一次。那么在统计省+市维度的日支付用户数,需要为杭州市、绍兴市各计1;但在省维度下,需要按用户去重,只能为浙江省计1。针对这种情况,通常就需要以Cube的方式完成数据预计算,同时每个维度组合都需要进行去重操作,因为不可累加。本文将此种场景简称为去重Cube。

二、常见的实现方法

直接计算,每个维度组合单独计算。比如单独生成省、省+市、省+市+区等维度组合的多张表。每个表只计算固定的维度。然后是数据膨胀再计算,如Union All或者Lateral View Explode或者MaxCompute的 Cube计算功能,通过数据膨胀实现一行数据满足多种维度组合的数据计算方法,如下图所示。

这三种写法其实都类似,重点都在于对数据进行膨胀,再进行去重统计。其执行流程如下图所示,核心思路都是先把数据"膨胀"拆为多行,再按照“普通”的Distinct去重统计,因此性能上本身无太大差异,主要在于代码可维护性上。

三、性能分析

上述方法核心都是先把数据"膨胀"拆为多行,再按照“普通”的Distinct去重统计,本身性能无太大差异,主要在于代码可维护性上。这几种方案计算消耗会随着所需维度组合线性增加,同时还要叠加Distinct本身的计算性能差的影响。

在实际实验中,我们发现,去重Cube的计算过程中,80%+的计算成本消耗在数据膨胀和数据传输上。比如高管核心指标场景,需要计算各种组合维度下的支付用户数以支持分析。实际实验中,选取100亿数据x25种维度组合进行测试,实际执行任务如下图所示,其中R3_2为核心的数据膨胀过程,数据膨胀近10倍,中间结果数据大小由100GB膨胀至1TB、数据量由100亿膨胀至近1300亿,大部分计算资源和计算耗时都花在数据膨胀和传输上了。若实际的组合维度进一步增加的话,数据膨胀大小也将进一步增加。

四、一种新的思路

首先对问题进行拆解下,去重Cube的计算过程核心分为两个部分,数据膨胀+数据去重。数据膨胀解决的是一行数据同时满足多种维度组合的计算,数据去重则是完成最终的去重统计,核心思路还是在于原始数据去匹配结果数据的需要。其中数据去重本身的计算量就较大,而数据膨胀会导致这一情况加剧,因为计算过程中需要拆解和在shuffle过程中传输大量的数据。数据计算过程中是先膨胀再聚合,加上本身数据内容的中英文字符串内容较大,所以才导致了大量的数据计算和传输成本。

而我们的核心想法是能否避免数据膨胀,同时进一步减少数据传输大小。因此我们联想到,是否可以采用类似于用户打标签的数据打标方案,先进行数据去重生成UID粒度的中间数据,同时让需要的结果维度组合反向附加到UID粒度的数据上,在此过程中并对结果维度进行编号,用更小的数据结构去存储,避免数据计算过程中的大量数据传输。整个数据计算过程中,数据量理论上是逐渐收敛的,不会因为统计维度组合的增加而增加。

4.1.核心思路

核心计算思路如上图,普通的数据膨胀计算cube的方法,中间需要对数据进行膨胀,再聚合,其中结果统计需要的组合维度数就是数据膨胀的倍数,比如上述的“省、省+市”共计两种维度组合,数据预计要膨胀2倍。

而新的数据聚合方法,通过一定的策略方法将维度组合拆解为维度小表并进行编号,然后将原本的订单明细数据聚合至用户粒度的中间过程数据,其中各类组合维度转换为数字标记录至用户维度的数据记录上,整个计算过程数据量是呈收敛聚合的,不会膨胀。

4.2.逻辑实现

  • 明细数据准备:以用户线下支付数据为例,明细记录包含订单编号、用户ID、支付日期、所在省、所在市、支付金额。最终指标统计需求为统计包含省、市组合维度+支付用户数的多维Cube。

订单编号

用户ID

支付日期

所在省

所在市

支付金额

U001

2023-11-11

浙江省

杭州市

1.11

U001

2023-11-11

浙江省

绍兴市

2.22

U002

2023-11-11

浙江省

杭州市

3.33

U003

2023-11-11

江苏省

南京市

4.44

U003

2023-11-11

浙江省

温州市

5.55

U004

2023-11-11

江苏省

南京市

6.66

整体方案流程如下图。

  • STEP1:对明细数据进行所需的维度提取(即Group By对应字段),得到维度集合。

  • STEP2:对得到的维度集合生成Cube,并对Cube的行进行编码 (假设最终需要所在省、所在省+所在市2种组合维度),可以用ODPS的Cube功能实现,再根据生成的Cube维度组合进行排序生成唯一编码。

    原始维度:所在省

    原始维度:所在省

    Cube 维度:所在省

    Cube 维度:所在市

    Cube行ID(可通过排序生成)

    浙江省

    杭州市

    浙江省

    ALL

    1

    浙江省

    杭州市

    浙江省

    杭州市

    2

    浙江省

    绍兴市

    浙江省

    ALL

    1

    浙江省

    绍兴市

    浙江省

    绍兴市

    3

    浙江省

    温州市

    浙江省

    ALL

    1

    浙江省

    温州市

    浙江省

    温州市

    4

    江苏省

    南京市

    江苏省

    ALL

    5

    江苏省

    南京市

    江苏省

    南京市

    6

  • STEP3:将Cube的行编码,根据映射关系回写到用户明细上,可用Mapjoin的方式实现。

订单编号

用户ID

支付日期

所在省

所在市

汇总Cube ID

U001

2023-11-11

浙江省

杭州市

[1,2]

U001

2023-11-11

浙江省

绍兴市

[1,3]

U002

2023-11-11

浙江省

杭州市

[1,2]

U003

2023-11-11

江苏省

南京市

[5,6]

U003

2023-11-11

浙江省

温州市

[1,4]

U004

2023-11-11

江苏省

南京市

[5,6]

  • STEP4:汇总到用户维度,并对 Cube ID集合字段进行去重 (可以用ARRAY 的DISTINCT)

  • STEP5:按照Cube ID进行计数计算(由于STEP4已经去重啦,因此这里不需要再进行去重);然后按照映射关系进行维度还原。

    Cube ID

    下单用户数指标

    Cube 维度还原:所在省

    Cube 维度还原:所在市

    1

    3

    浙江省

    ALL

    2

    2

    浙江省

    杭州市

    3

    1

    浙江省

    绍兴市

    4

    1

    浙江省

    温州市

    5

    2

    江苏省

    ALL

    6

    2

    江苏省

    江苏省

  • Over~

4.3.代码实现

WITH-- 基本的明细数据表准备base_dwd AS (SELECT pay_no,user_id,gmt_pay,pay_amt,prov_name,prov_code,city_name,city_codeFROM tmp_user_pay_order_detail-- 生成多维Cube,并进行编码,dim_cube AS (-- Step02:CUbe生成SELECT *,DENSE_RANK() OVER(PARTITION BY 1 ORDER BY cube_prov_name,cube_city_name) AS cube_idFROM (SELECT dim_key,COALESCE(IF(GROUPING(prov_name) = 0,prov_name,'ALL'),'na') AS cube_prov_name,COALESCE(IF(GROUPING(city_name) = 0,city_name,'ALL'),'na') AS cube_city_nameFROM (-- Step01:维度统计SELECT CONCAT('',COALESCE(prov_name ,''),'#',COALESCE(city_name ,''),'#') AS dim_key,prov_name,city_nameFROM base_dwdGROUP BY prov_name,city_name) baseGROUP BY dim_key,prov_name,city_nameGROUPING SETS ((dim_key,prov_name),(dim_key,prov_name,city_name)-- 将CubeID回写到明细记录上,并生成UID粒度的中间过程数据,detail_ext AS (-- Step04:指标统计SELECT user_id,ARRAY_DISTINCT(SPLIT(WM_CONCAT(';',cube_ids),';')) AS cube_id_arryFROM (-- Step03:CubeID回写明细SELECT /*+ MAPJOIN(dim_cube) */user_id,cube_idsFROM (SELECT user_id,CONCAT('',COALESCE(prov_name,''),'#',COALESCE(city_name,''),'#') AS dim_keyFROM base_dwd) dwd_detailJOIN (SELECT dim_key,WM_CONCAT(';',cube_id) AS cube_idsFROM dim_cubeGROUP BY dim_key) dim_cubeON dwd_detail.dim_key = dim_cube.dim_key) baseGROUP BY user_id-- 指标汇总并将CubeID翻译回可理解的维度,base_dws AS (-- Step05:CubeID翻译SELECT cube_id,MAX(prov_name) AS prov_name,MAX(city_name ) AS city_name,MAX(uid_cnt ) AS user_cntFROM (SELECT cube_id AS cube_id,COUNT(1) AS uid_cnt,CAST(NULL AS STRING) AS prov_name,CAST(NULL AS STRING) AS city_nameFROM detail_extLATERAL VIEW EXPLODE(cube_id_arry) arr AS cube_idGROUP BY cube_idUNION ALLSELECT CAST(cube_id AS STRING) AS cube_id,CAST(NULL AS BIGINT) AS uid_cnt,cube_prov_name AS prov_name,cube_city_name AS city_nameFROM dim_cube) baseGROUP BY cube_id-- 大功告成,输出结果!!!SELECT prov_name,city_name,user_cntFROM base_dws

  • 实际的执行过程(ODPS的Logview)如下图。

4.4.实验效果

左边是基于Cube打标方案的新链路。实验过程中将实验数据由100亿增加至200亿,组合维度数由原来的25个增加至50种组合维度,整体耗时在18分钟,若只计算和原始数据量、组合维度均相同的数据,整体计算耗时可控制在10分钟内。

右边是基于数据膨胀计算的老链路。实验数据设定为100亿,组合维度数为25种,中间过数据将膨胀至1300亿+,数据大小更是膨胀至1TB+,整体耗时47分钟。若此方案扩展至新方法的200亿数据x50种组合维度,中间过程数据将膨胀至4000亿+,数据大小增加将膨胀至3TB+,整体计算耗时预估将达到2.5小时+。

新方法目前已经在业务核心高管链路上线,在数据统计维度组合、数据计算量都大幅增加的情况下,整体核心指标产出相较于以往,进一步提前1小时以上,有效的保障了相关核心指标数据的稳定性。

4.5.方案总结

常见的基于数据膨胀的Cube计算方法,数据计算大小和过程数据传输量将随着组合维度的数量呈线性增长,组合维度数越多,花费在数据膨胀与Shuffle传输的资源和耗时占比越高。在实验过程中,100亿实验数据x25种维度组合场景,过程数据已经膨胀至1300亿+,数据大小由100GB膨胀至1TB,当数据量和维度组合数进一步增加时,整个计算过程基本上难以完成。

为了解决数据膨胀过程中产生的大量过程数据,我们基于数据打标的思路反向操作,先对数据聚合为UID粒度,过程中将需要的维度组合转化编码数字并赋予明细数据上,整个计算过程数据呈收敛聚合状,数据计算过程较为稳定,不会随着维度组合的进一步增加而大幅增加。在实验中,将实验数据由100亿增加至200亿+,组合维度数由原来的25个增加至50种组合维度,整体耗时控制在18分钟左右。若同等的数据量,采用老的数据膨胀方案,中间过程数据将膨胀至4000亿+,数据大小将增加至3TB+,整体计算耗时将达到2.5小时+。

综上,当前的方案整体性能相较于以往有大幅度的提升,并且不会随着维度组合的增加而有明显的增加。但当前的方案也有不足之处,即代码的可理解性和可维护性,过程中的打标计算过程虽然流程较为固定,但整体上需要有个初始化理解的过程,目前尚无法做到普通UnionAll/Cube等方案的易读和易写。另外,当组合维度数较少(即数据膨胀倍数不高)时,两者的性能差异不大,此时建议还是用原始普通的Cube计算方案;但当组合维度数达几十倍时,可以改用这种数据打标的思路进行压缩,毕竟此时的性能优势开始凸显,并且维度组合数越高,此方案的性能优势越大。

五、其他方案

BitMap方案。核心思路在于将不可累计的数据指标,通过可累加计算的数据结构,近似实现可累加指标的效果。具体实现过程方案是对用户ID进行编码,存入BitMap结构中,比如一个二进制位表示一个用户是否存在,消耗1个Bit。维度统计上卷时,再对BitMap的数据结构进行合并和计数统计。

HyperLogLog方案。非精确数据去重,相对于Distinct的精确去重,性能提升明显。

这两种方案,性能上相对于普通的Cube计算有巨大的提升,但BitMap方案需要对去重统计用的UID进行编码存储,对一般用户的理解和实操成本较高,除非系统级集成此功能,不然通常需要额外的代码开发实现。而HyperLogLog方案的一大弊端就是数据的非精确统计。

直击斯坦福大学开源机械臂又进化

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
那英开演唱会半个娱乐圈都来了,网友却在问:他们是花钱买的票吗

那英开演唱会半个娱乐圈都来了,网友却在问:他们是花钱买的票吗

草莓解说体育
2026-08-24 00:01:06
追到校草3个月,我突然没了兴致,打算提分手,无意间刷到他小号发文:我和她恋爱只是玩乐。我舒了口气,顺手点赞,他却慌了

追到校草3个月,我突然没了兴致,打算提分手,无意间刷到他小号发文:我和她恋爱只是玩乐。我舒了口气,顺手点赞,他却慌了

晓艾故事汇
2026-08-23 16:04:55
300亿被冻结!曾经吊打沃尔沃的国产神车,彻底宣告落幕!

300亿被冻结!曾经吊打沃尔沃的国产神车,彻底宣告落幕!

青眼财经
2026-08-05 23:51:12
北京这一晚,内娱的人情冷暖江湖地位,在那英身上体现的淋漓尽致

北京这一晚,内娱的人情冷暖江湖地位,在那英身上体现的淋漓尽致

草莓解说体育
2026-08-23 04:45:05
伤得很深!男子打赏女主播近300万,想结婚时才知对方女儿都20岁了:我只顾为爱冲锋,结果她全是假话

伤得很深!男子打赏女主播近300万,想结婚时才知对方女儿都20岁了:我只顾为爱冲锋,结果她全是假话

极目新闻
2026-04-10 15:54:54
雷竞技资讯:BLG干碎AL后圣枪哥笑嘻!语音公开BLG全队都帮他出气

雷竞技资讯:BLG干碎AL后圣枪哥笑嘻!语音公开BLG全队都帮他出气

LPL夺冠了吗
2026-08-24 00:20:22
他从朝鲜回来无职务,授衔时得知自己是海南军区司令,怀疑听错了

他从朝鲜回来无职务,授衔时得知自己是海南军区司令,怀疑听错了

史之韵
2026-06-14 00:48:49
伊朗总统表示:伊朗应摆脱“既非战争、也非和平”状态 该国法尔斯省南部发现7.5万亿立方英尺天然气

伊朗总统表示:伊朗应摆脱“既非战争、也非和平”状态 该国法尔斯省南部发现7.5万亿立方英尺天然气

每日经济新闻
2026-08-23 23:25:44
许家印第二!又一“大佬”跑路被抓,诈骗989亿,超5万人血本无归

许家印第二!又一“大佬”跑路被抓,诈骗989亿,超5万人血本无归

牛牛叨史
2025-02-10 18:02:09
从年头富到年尾! 2027年最不缺钱的三大生肖,看看你上榜没?

从年头富到年尾! 2027年最不缺钱的三大生肖,看看你上榜没?

毅谈生肖
2026-08-23 11:58:10
伊劳拉时代首球!加克波无解世界波,利物浦14年英超首轮均破门

伊劳拉时代首球!加克波无解世界波,利物浦14年英超首轮均破门

奥拜尔
2026-08-24 00:51:58
逆转!武磊王者归来:梅开二度,上海海港4轮不败:超越上海申花

逆转!武磊王者归来:梅开二度,上海海港4轮不败:超越上海申花

足球狗说
2026-08-23 21:33:07
两性心理学:女人尝过床上这两种滋味后,再清醒也会沦陷

两性心理学:女人尝过床上这两种滋味后,再清醒也会沦陷

心理观察局
2026-08-22 06:28:17
咳了三年,肺都“瘪”了,瑞金医生却让她一天就出了院

咳了三年,肺都“瘪”了,瑞金医生却让她一天就出了院

上海交通大学医学院附属瑞金医院
2026-08-21 15:18:04
比缅北凶险100倍!曾经的旅游胜地,如今黄赌毒俱全,乱象随处可见

比缅北凶险100倍!曾经的旅游胜地,如今黄赌毒俱全,乱象随处可见

琅琊财经
2026-07-31 22:02:18
要变天!新首相上台就掀桌,直接废除前任计划!先打给了泽连斯基

要变天!新首相上台就掀桌,直接废除前任计划!先打给了泽连斯基

普览
2026-07-24 05:08:24
2亿多灵活就业人员怒了!原来北大张丹丹才是福利的受益者

2亿多灵活就业人员怒了!原来北大张丹丹才是福利的受益者

财话连篇
2026-08-22 18:44:09
官宣:嫦娥七号错过今年窗口,一场台风为什么可能要让它等近一年?

官宣:嫦娥七号错过今年窗口,一场台风为什么可能要让它等近一年?

翔说航天
2026-08-23 21:22:26
埃尔切vs巴萨:维克托-丘斯特、尼尼奥首发,亚马尔、拉菲尼亚出战

埃尔切vs巴萨:维克托-丘斯特、尼尼奥首发,亚马尔、拉菲尼亚出战

懂球帝
2026-08-24 02:43:30
台湾最新民调出炉,接近70%拒绝两岸统一,赖清德当局自欺欺人?

台湾最新民调出炉,接近70%拒绝两岸统一,赖清德当局自欺欺人?

小玡说故事
2026-08-22 13:55:15
2026-08-24 04:12:49
开源中国 incentive-icons
开源中国
每天为开发者推送最新技术资讯
7840文章数 34558关注度
往期回顾 全部

科技要闻

“英伟达发通知:涨价15%以上”

头条要闻

男子凌晨浏览黄色网站深陷"约炮"骗局 21.8万没了

头条要闻

男子凌晨浏览黄色网站深陷"约炮"骗局 21.8万没了

体育要闻

46岁小罗复出,为什么选了一支意丙球队?

娱乐要闻

王传君的舞台,藏着与乔任梁的过往

财经要闻

加拿大宣布“全额对等报复”美国新关税

汽车要闻

刘苗苗:极狐不押注单一爆款,增长进入体系化阶段

态度原创

时尚
亲子
本地
旅游
艺术

夏天别总穿白色T恤,试试这几款衬衫,配裤子裙子都显气质

亲子要闻

32岁的全职妈妈的重生之路终篇

本地新闻

《牛来》的一声“妈妈”,到底多少人被精神污染了

旅游要闻

旅居大理多年才懂,被低估的海东,藏着苍洱最绝的风景!

艺术要闻

我连新鲜白菜都买不起,土豪却花500万抢着买颗“烂包菜”?这世界终于疯成这样了!

无障碍浏览 进入关怀版