Hive专题-distinct优化

一、问题描述

在hive中count(distinct)很容易造成数据倾斜。但有时,“数据倾斜”又几乎是必然的。

我们来举个栗子:假设表sdk_session_details中记录了访问网站客户端会话信息,即:如果用户打开App客户端,则会产生一条会话信息记录在该表中,该表的粒度为“一次”会话,其中每次会话都记录了用户的唯一标示uuid,uuid是一个很长的字符串,假定其长度为64位。现在的需求是:每天统计当月的活用用户数——“月活跃用户数”(当月访问过app就为活跃用户)。我们以2016年1月为例进行说明,now表示当前日期。

这个问题逻辑上很简单,SQL也很容易写出来,如:

select
  count(distinct uuid)
from sdk_session_details t
where t.date >= '2019-06-01' AND t.date <= now

上述SQL代码中,很容易想到,时间跨度越大,上面的统计的数据量就会越大。更重要的是,在这种情况下,“数据倾斜”是必然的,因为只有一个reducer在进行count(distinct uuid)的计算,所有数据都流向唯一的一个reducer,不倾斜才怪。

二、分治优化一

其实,在count(distinct uuid)时候可以采用分治的思想来解决。对于上面的例子,首先我们按照uuid的前n位进行group by,并做count(distinct uuid)操作,然后再对所有的count(distinct uuid)结果进行求和。这里先把SQL写出来,然后再做分析。

-- 外层select求和
select
  sum(part_num) mau
from
(
  -- 内层select分别进行count(distinct)计算
  select
    substr(uuid, 1, 3) uuid_part,
    count(distinct uuid) as part_num
  from sdk_session_details 
  where date >= '2016-01-01' and date<= now
  group by substr(uuid, 1, 3)
) t;

这种方法的好处在于,在不同的reducer各自进行count(distinct uuid)计算,充分发挥hadoop的优势,然后进行求和。

三、分治优化二

其实,很多博客中都记录了使用group by操作代替count(distinct uuid)操作,但有时仅仅使用group by操作还不够,还需要加点小技巧。 还是先来看一下代码:

--  第三层select
select
  sum(s.part_num) mau
from
(
  -- 第二层select
  select
    tag,
    count(*) part_num
  from
  (
      -- 第一层select
    select
      uuid, 
      cast(rand() * 100 as bigint) tag  -- 为去重后的uuid打上标记,标记为:0-100之间的整数。
    from sdk_session_details 
    where date >= '2016-01-01' and date <= now
    group by uuid   -- 通过group by,保证去重
   ) t
  group by tag
) s;
  • 第一层select:对uuid进行去重,并为去重后的uuid打上整数标记
  • 第二层select:按照标记进行分组,统计每个分组下uuid的个数
  • 第三层select:对所有分组进行求和

上面这个方法最关键的是为每个uuid进行标记,这样就可以对其进行分组,分别计数,最后求和。如果数据量确实很大,也可以增加分组的个数。例如:cast(rand() * 1000 as bigint) tag

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值