背景
在开发时候经常需要统计最近N天数据,用户数目去重等统计指标
select visitor_id
from
(
select item_id, count(distinct visitor_id) as ipv_uv_1d_001
from crm_bi.log_vst_di
where ds <= '${bizdate}'
and ds >= to_char(dateadd(to_date('${bizdate}','yyyymmdd'),-29,'dd'),'yyyymmdd')
group by item_id
) a
上面可能会造成严重问题,需要的Map instance数目太多。超过99999个限制。为什么Instance个数需要那么多呢?原因:每天的日志数据很大,30天的数据量更是惊人,这时候Select 操作需要大量的Map Instance,结果查过了Instance的上限,代码无法运行
目的
如何计算长周期的指标,又不影响性能呢?
- 多天汇总的问题根源在数据量问题,如果把数据量降低,就可以解决
- 减少数据量最直接办法就是把每天的数据量都减少,因此需要构建临时表,对1d的数据进行轻度汇总,这样就能去掉很多重复数据 ,减少数据量。
方案
- 构建中间表,每天汇总一次
- 计算多天的数据,依赖中间表进行汇总
insert overwrite table demo_itm_visitor_xx(ds='${bizdate}')
select item_id, visitor_id
from (
select item_id, visitor_id
from crm_bi.log_vst_di
where ds='${bizdate}'
group by item_id, visitor_id
) a
对demo_itm_visitor_xx表进行30天汇总
select visitor_id
from
(select item_id
,count(distinct visitor_id) as ipv_uv_1d_001
from demo_itm_visitor_xx
where ds <= '{bizdate}'
and ds >= to_char(dateadd(to_date('${bizdate}','yyyymmdd'),-29,'dd'),'yyyymmdd')
group by item_id
) a
思考
上面方法优点是提高了性能,缺点是每次计算多天的数据时候,都要N个分区的数据那么是否有一种方法,不需要计算,已经有一个存放最近N天数据的
增长累计方式计算长周期指标
例子: 求最近1天店铺的老访客数,老访客定义为:最近180天有访问,就算老访客
思路:
-
将买家从前天开始往前推180天,记做集合A;也就是说从
-180到-1
的访客数据都在集合A中了
更新公式为:An=An-1+Ao-A ,即今天的nd数据=历史全量数据+今天的增量数据-最老那天的增量数据 -
使用集合A和昨天的访客做Join操作。如果在集合A中,则是老访客,否则是新访客。
网友评论