规模化产出指标的思路之一

需求背景

自定义指标功能初期上线时,直接从埋点底层表进行数据获取,整体运行效率比较低。当实验组数较多且添加的自定义指标个数也比较多的时候,任务数量会暴增,会出现集中阻塞平台统计任务的情况,导致平台整体的数据产出延迟,同时如果在排队阶段也会影响线上服务的提供(主要是可用流量计算的功能)。

目前需要针对这个问题,输出相应的解决方案,整体的方向为:

  • 结合用户在平台设置的自定义指标配置信息,构建中间层,将大表变成小表,提高整体取数效率
  • 规模化产出数据,减轻AB平台取数的压力
  • 由于用户添加自定义指标后,会有补跑数据的需求,所以需要满足这部分的需求,需要保证中间表数据的充分性。这是本次优化的难点所在。

由于用户设置指标的规则设定自由度较高,且涉及拓展参数的方式,用传统的表关联方式批量产出不太可行。


方案构思

大部分公司使用宽表来存储指标的定义,即一列字段代表一个指标,这类方法在明确指标的需求上是能够满足需求的,跑数效率能得到比较好的保证,但有比较明显的缺点,即新增指标则需要频繁地去修改表结构,后期不好维护,且犯错几率也不断提升。

为了保证指标接入的拓展性,只有纵表才可以满足需求,并结合宽表本身的优点,输出如下方案:

  1. 将埋点规则利用一定的映射函数转化为对应的指标标签(类0-1型数据),并利用宽表的结构完成所有指标的规则输出结果。
  2. 利用行列转化技术,将宽表结构的数据转化为纵表结构。(PS:这里面可能遇到稀疏矩阵的问题,定义为:在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵
  3. 后面就可以进行常规的PV和UV统计,得到想要的指标数据。

整体的实现思路
image2021-5-13_22-23-20


脚本实现

select ab_group_id, metric,count(1) as uv,sum(cnt) as pv
from
(
    select dt,user_id,ab_group_id,metric,count(1) as cnt
    from
    (
        select dt,user_id,ab_info,metric
        from
        (
            select dt,actor_user_id as user_id,ab_info,
            concat(case when event_id = 'e_live_enter'  and get_json_object(custom, '$.live_enter_source') in ('idle-push-follow') then 'metric1' else '0' end
                  ,',',case when event_id = 'e_live_enter'  and get_json_object(custom, '$.live_enter_source') in ('idle-push-follow') then 'metric2' else '0' end) as metrics
            from XXX
            where dt='2021-05-10'
        ) t2 lateral view explode(split(t2.metrics,',')) t as metric
        where metric <> '0') t3 lateral view explode(split(t3.ab_info,'\u0001')) tt as ab_group_id
    group by dt,user_id,ab_group_id,metric
) z
group by ab_group_id, metric
作者:Qingyun
                
comments powered by Disqus