zoukankan      html  css  js  c++  java
  • Hive SQL count(distinct)效率问题及优化

    上周拿到了我的第一个工作任务,统计一个按天分区每天都有百亿条数据条的hive表中account字段的非重用户数(大概两千万)。后来又更改为按id字段分别统计每个id的用户数。

    按照我数据库老师的教导,我很轻易的跳出来了count(distinct account)这个句子。然后写上了一行查询,等待了四个小时,然后map反着跑

    就知道没这么容易的任务。。

    然后想起来Hive SQL 基于的mapreduce是并行计算,百亿的数据可不是平时测试时的mysql里的几百条数据。

    这么想来应该是map和reduce的内存不够,

    set mapreduce.map.memory.mb=48192;
    set mapreduce.reduce.memory.mb=48192;

    执行语句

    select countdistinct account) from...where...

    继续mapreduce,三个小时后报错error in shuffle in fetcher#3. shuffle过程又出问题了。

    找呀找,reducer只有1? 那还怎么并行?果断

    set mapred.reduce.tasks=1000;

    又进行查询,发现reducer 还是1。 只能求助于万能的Internet了。

    原来因为加入distinct,map阶段不能用combine消重,数据输出为(key,value)形式然后在reduce阶段进行消重。

    重点是,Hive在处理COUNT这种“全聚合(full aggregates)”计算时,它会忽略用户指定的Reduce Task数,而强制使用1。

    示意图如下

    解决办法:转换为子查询,转化为两个mapreduce任务  先select distinct的字段,然后在count(),这样去重就会分发到不同的reduce块,count依旧是一个reduce但是只需要计数即可。

    select count*fromselect distinct account form tablename where...)t;

    这样大概半小时可以得到结果。

    后来需求改变为对这个表按account的类型(字段名为id)统计每个类型的account非重复数。

    如果按照上述方法,在查询条件添加 where id=..,这样每个查询都需要半小时,效率很低。

    优化方法:利用gourp by 按id,account分组,存入一个临时表 只需要对临时表进行统计即可

    insert overwrite table temp select id,account,count(1) as num from tablename group by id,account;

    这样temp表里的数据直接就是非重数据,并且按id升序排序,按id筛选 count(*)即可。 sum(num)也可统计总数。

    参考:http://blog.csdn.net/xiewenbo/article/details/29559075

  • 相关阅读:
    BZOJ4892: [Tjoi2017]dna
    BZOJ4307: Maishroom & Class
    NCEE2018游记
    BZOJ3720: Gty的妹子树
    BZOJ5055: 膜法师
    「奇技淫巧」博客园页面美化(差不多是划水
    白痴qwerta的胡言乱语(一句话日度感想?
    关于qwerta
    NOIP2018退役记
    「NOIP2017」「LuoguP3952」 时间复杂度(模拟,栈
  • 原文地址:https://www.cnblogs.com/ling1995/p/7339424.html
Copyright © 2011-2022 走看看