Hive中的count(distinct)如何优化

这篇文章主要为大家展示了“Hive中的count(distinct)如何优化”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Hive中的count(distinct)如何优化”这篇文章吧。

10年积累的网站设计制作、做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先做网站后付款的网站建设流程,更有顺德免费网站建设让你可以放心的选择与我们合作。


问题描述

COUNT(DISTINCT xxx)在hive中很容易造成数据倾斜。针对这一情况,网上已有很多优化方法,这里不再赘述。 
但有时,“数据倾斜”又几乎是必然的。我们来举个例子:

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

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

SELECT  COUNT(DISTINCT uuid)FROM detail_sdk_session tWHERE t.date >= '2016-01-01' AND t.date <= now

上述SQL代码中,now表示当天的日期。很容易想到,越接近月末,上面的统计的数据量就会越大。更重要的是,在这种情况下,“数据倾斜”是必然的,因为只有一个reducer在进行COUNT(DISTINCT uuid)的计算,所有的数据都流向唯一的一个reducer,不倾斜才怪。

 

优化1

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

-- 外层SELECT求和SELECT  SUM(mau_part) mauFROM(  -- 内层SELECT分别进行COUNT(DISTINCT)计算  SELECT    substr(uuid, 1, 3) uuid_part,    COUNT(DISTINCT substr(uuid, 4)) AS mau_part  FROM detail_sdk_session  WHERE partition_date >= '2016-01-01' AND partition_date <= now  GROUP BY substr(uuid, 1, 3)) t;
 

上述SQL中,内层SELECT根据uuid的前3位进行GROUP BY,并计算相应的活跃用户数COUNT(DISTINCT),外层SELECT求和,得到最终的月活跃用户数。 
这种方法的好处在于,在不同的reducer各自进行COUNT(DISTINCT)计算,充分发挥hadoop的优势,然后进行求和。

注意,上面SQL中,n设为3,不应过大。 
为什么n不应该太大呢?我们假定uuid是由字母和数字组成的:大写字母、小写字母和数字,字符总数为26+26+10=62。理论上,内层SELECT进行GROUP BY时,会有 62^n 个分组,外层SELECT就会进行 62^n 次求和。所以n不宜过大。当然,如果数据量十分巨大,n必须充分大,才能保证内层SELECT中的COUNT(DISTINCT)能够计算出来,此时可以再嵌套一层SELECT,这里不再赘述。

 

优化2

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

--  第三层SELECTSELECT  SUM(s.mau_part) mauFROM(  -- 第二层SELECT  SELECT    tag,    COUNT(*) mau_part  FROM  (      -- 第一层SELECT    SELECT      uuid,       CAST(RAND() * 100 AS BIGINT) tag  -- 为去重后的uuid打上标记,标记为:0-100之间的整数。    FROM detail_sdk_session    WHERE partition_date >= '2016-01-01' AND partition_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

以上是“Hive中的count(distinct)如何优化”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!

网页标题:Hive中的count(distinct)如何优化
标题路径:https://www.cdcxhl.com/article28/podocp.html

成都网站建设公司_创新互联,为您提供电子商务网站制作移动网站建设域名注册定制网站品牌网站制作

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

网站托管运营