长周期指标的计算优化方案

简介: 1 背景 在电子商务公司(如淘宝),对用户的数据分析的角度和思路可谓是应有尽有、层出不穷。所以在电商数据仓库和商业分析场景里,经常需要计算最近N天访客数、最近N天的购买用户数、老客数等等类似的指标。这些指标有一个共同点:都需要根据用户在电商平台上(或网上店铺)一段时间积累的数据进行计算(这里讨论的前提是数据都存储在MaxCompute上)。

1 背景

在电子商务公司(如淘宝),对用户的数据分析的角度和思路可谓是应有尽有、层出不穷。所以在电商数据仓库和商业分析场景里,经常需要计算最近N天访客数、最近N天的购买用户数、老客数等等类似的指标。这些指标有一个共同点:都需要根据用户在电商平台上(或网上店铺)一段时间积累的数据进行计算(这里讨论的前提是数据都存储在MaxCompute上)。
一般情况下,这些指标的计算方式就是从日志明细表中计算就行了,如下代码计算商品的最近30天访客数:

select   item_id         --商品id    
     ,count(distinct visitor_id) as ipv_uv_1d_001   
from     用户访问商品日志明细表   
where    ds <= ${bdp.system.bizdate}   
and ds >=to_char(dateadd(to_date(${bdp.system.bizdate},'yyyymmdd'),-29,'dd'),'yyyymmdd')     
 group by item_id

  但是当每天的日志量很大时,上面代码存在一个严重的问题,需要的Map Instance个数太多,甚至会超过99999个Instance个数的限制,Map Task就没有办法顺利执行,更别说后续的操作了。为什么Instance个数需要那么多呢?原因:每天的日志数据很大,30天的数据量更是惊人。这时候Select 操作需要大量的Map Instance,结果查过了Instance的上限,代码无法运行

2 目的

  如何计算长周期的指标,又不影响性能?

  1. 多天汇总的问题根源是数据量的问题,如果把数据量给降低了,就可以解决这个问题了。

  2. 减少数据量最直接的办法是把每天的数据量都给减少,因此需要构建临时表,对1d的数据进行轻度汇总,这样就能去掉很多重复数据,减少数据量。

3 方案

  1. 构建中间表,每天汇总一次,比如对于上面的例子,构建一个item_id+visitor_id粒度的中间表

  2. 计算多天的数据,依赖中间表进行汇总

  例子如下:

   step1:构建item_id+visitior_id粒度的日汇总表,记作A

insert overwrite table mds_itm_vsr_xx(ds='${bdp.system.bizdate} ')
select item_id,visitor_id,count(1) as pv
from
    (
     select   item_id,visitor_id
     from     用户访问商品日志明细表    
     where    ds =${bdp.system.bizdate}  
     group by item_id,visitor_id
    )a

  setp2:对A进行30天汇总

   select   item_id
            ,count(distinct visitor_id) as uv
            ,sum(pv) as pv
     from      mds_itm_vsr_xx
     where    ds <= '${bdp.system.bizdate} '
     and      ds >= to_char(dateadd(to_date('${bdp.system.bizdate} ','yyyymmdd'),-29,'dd'),'yyyymmdd')
     group by item_id

4 影响及思考

  上面讲述的方法,对每天的访问日志明细数据进行单天去重,从而减少了数据量,提高了性能。缺点是每次计算多天的数据的时候,都要N个分区的数据,那么能不能有一种方式,不需要读取N个分区的数据,而是把N个分区的数据压缩合并成一个分区的数据,让一个分区的数据包含历史数据的信息。业务上是有类似场景的,有如下方式:

1. 增量累计方式计算长周期指标

  例子:求最近1天店铺商品的老买家数,老买家数的算法定义为:过去一段时间有购买的买家(比如过去30天)。
一般情况下,老买家数计算方式:

select   item_id         --商品id    
       ,buyer_id as old_buyer_id
from     用户购买商品明细表   
where    ds < ${bdp.system.bizdate}   
and ds >=to_char(dateadd(to_date(${bdp.system.bizdate},'yyyymmdd'),-29,'dd'),'yyyymmdd')     
 group by item_id
        ,buyer_id

  改进思路:
   1. 维护一张店铺商品和买家购买关系的维表记作表A,记录买家和店铺的购买关系,以及第一次购买时间,最近一次购买时间,累计购买件数,累计购买金额等等信息
   2. 每天使用最近1天的支付明细日志更新表A的相关数据
   3. 计算老买家时,最需要判断最近一次购买时间是否是30天之内就行了,从而做到最大程度上的数据关系对去重,减少了计算输入数据量

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
分布式计算 关系型数据库 MySQL
DataWork数据处理问题之调整并发数量如何解决
DataWork数据处理是指使用DataWorks平台进行数据开发、数据处理和数据治理的活动;本合集将涵盖DataWork数据处理的工作流程、工具使用和问题排查,帮助用户提高数据处理的效率和质量。
42 4
|
6月前
|
数据采集 监控 数据挖掘
分析指标波动,数据模型得这么建
分析指标波动,数据模型得这么建
|
3月前
|
敏捷开发 数据可视化 安全
测试度量指标
测试度量指标
|
4月前
流量数据指标分析
流量数据指标分析
23 0
|
8月前
|
SQL BI iOS开发
不要再因为数据指标吵架了!
不要再因为数据指标吵架了!
|
9月前
|
Serverless
函数计算减少冷启动对性能的影响
函数计算减少冷启动对性能的影响
311 1
|
9月前
|
前端开发 算法 测试技术
【软考学习5】流水线基本概念、周期执行时间、吞吐率、加速比和效率的计算
【软考学习5】流水线基本概念、周期执行时间、吞吐率、加速比和效率的计算
575 0
|
数据处理 计算机视觉
计算时间序列周期的三种方法
周期是数据中出现重复模式所需的时间长度。更具体地说,它是模式的一个完整周期的持续时间。在这篇文章中,将介绍计算时间序列周期的三种不同方法。
184 0
计算时间序列周期的三种方法
|
监控 NoSQL Java
|
存储 SQL Oracle
如何快速实现多指标计算
如何快速实现多指标计算
259 0