当前位置:   article > 正文

【Hive】数据倾斜之join和group by导致的解决案例_group by 数据倾斜 给id加前缀

group by 数据倾斜 给id加前缀

最近工作上遇到数据量特别大的任务,一天20T左右,和一些维表关联时,出现了数据倾斜的情况。这边记录一下解决的方法。

背景

由于工作数据敏感问题,这边用其他场景来模拟(纯属虚构的场景和数据,侵删)。
假设表1:happy_info 是全球192个国家的开心次数信息,有如下字段:(开心一次,就会记录一次,一个id会上报多条记录)

  1. 人员id 国籍 是否开心 开心时刻
  2. (id) (country) (is_happy) (happy_moment)
  3. 00001 中国 1 2020-01-20
  4. 00001 中国 1 2020-01-21
  5. 00001 中国 1 2020-01-23
  6. 00002 中国 1 2020-01-21
  7. 00003 印度 1 2020-01-20
  8. 00004 美国 1 2020-01-20
  9. 00005 英国 1 2020-01-22
  10. 00006 中国 1 2020-01-20
  11. 00007 美国 1 2020-01-20
  12. 00008 中国 1 2020-01-23
  13. ... ... ... ...
  14. (剩余70亿条信息)

表2:country_info 是筛选出的50个国家对应英文名的维表:

  1. 中文名 英文名
  2. (cn_name) (en_name)
  3. 中国 China
  4. 英国 England
  5. 美国 America
  6. 印度 India
  7. ... ...
  8. (共50个各国家的英文名信息)

需求

假设现有全球192个国家70亿人的开心次数信息,求表250个国家近半年的平均开心次数,要求有国籍的英文名信息。

优化之前的sql

  1. select
  2. country
  3. ,en_name
  4. ,sum(happy_times) as all_happy_times
  5. ,count(id) as all_user
  6. ,sum(happy_times) / count(id) as avg_happy_times
  7. from
  8. (
  9. select /*+ MAPJOIN(b)*/ id, country, en_name, count(id) as happy_times
  10. from
  11. (
  12. select
  13. country
  14. ,id
  15. from happy_info
  16. ) a
  17. join
  18. (
  19. select cn_name, en_name
  20. from country_info
  21. ) b
  22. on a.country = b.cn_name
  23. group by id, country, en_name
  24. ) a
  25. group by
  26. country
  27. ,en_name

当时的思路是先把表1中的192个国家限定在表2中的50个里面。再去进去group by统计。由于中国人天天开心,而且此时很多,发现数据倾斜的情况。

优化后的sql

  1. select
  2. country
  3. ,en_name
  4.    ,all_happy_times
  5.    ,all_users
  6.    ,all_happy_times / all_users as avg_happy_times
  7. from
  8.     (
  9.     select
  10.     country
  11.     ,sum(total_user) as all_users
  12.     ,sum(tot_happy_times) as all_happy_times
  13.     from
  14.         (
  15.             select
  16.             country
  17.             ,rnd --对每个国家以及随机数进行聚合
  18.             ,count(1) as total_user
  19.             ,sum(cnt) as tot_happy_times
  20.             from
  21.                 (
  22.                     select
  23.                         country
  24.                         ,round(rand()*1000) as rnd --利用随机数分成1000份
  25.                         ,id
  26.                         ,count(1) as cnt
  27.                     from happy_info
  28.                     group by
  29.                         country
  30.                         ,id
  31.                 ) a
  32.             group by country, rnd
  33.         ) a
  34.     group by country
  35.     ) a
  36.     join
  37.         (
  38. select cn_name, en_name
  39. from country_info
  40.         ) b
  41.     on a.country = b.cn_name

思路:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/976016
推荐阅读
相关标签
  

闽ICP备14008679号