SQL如何解决数据倾斜

在优化任务里,最常碰到的一个问题,就是数据倾斜。简单来说,数据倾斜就是一张表的关联键或者聚合键中,某个或者某些特定数值出现的频率远大于其它数值,经过shuffle之后,某些节点的计算量远大于其他节点,使得hadoop无法发挥分布式计算的优势,最终导致计算时间过长。

一般来说,数据倾斜主要分为JOIN倾斜和Group By倾斜。

JOIN倾斜出现的场景一般有以下几种:
1)大表join小表
使用mapjoin的方式(在select语句中使用Hint提示/*+ mapjoin(<table_name>) */才会执行mapjoin),这个操作会将所有的小表全量复制到每个map任务节点,然后再将小表缓存在每个map节点的内存里与大表进行join工作。这样即节省了shuffle的时间,又避免了shuffle后的倾斜。mapjoin在Map阶段会将指定表的数据全部加载在内存中,因此指定的表仅能为小表,且表被加载到内存后占用的总内存不得超过一定的阈值,阈值的上限在各家公司基于hadoop研发的大数据引擎里都不太一样。

2)大表join大表或者中表
一般有两种常用的思路:
a. 看是否关联键有异常值(比如空值,null等),可采用coalesce(column, rand()*9999)来进行空值分发或者先进行where uid is not null 的条件过滤。在使用不太熟悉的表数据前,建议对数据探查,对数据质量有个基本认识。
b. 采用手动切分热值的方法。可通过对关联键进行groupby取count值再倒叙排列的方式探查出热值有哪些(比如取top20),然后两张表分别过滤出热值的数据进行join(一般过滤完后数据量较小,可用mapjoin),而非热点值用正常的mergejoin,最后再将结果union all起来。目前hive已有对应的skewjoin参数可以设置,方便简单。
c. 如果其中一张表z的数据量并非很大,但又不能使用mapjoin时,可以采用膨胀法。简单来说,在表z中新增一列number,表x的每一行数都分别对应number列中的数值1-5(即将表z的每一行数据膨胀5倍),然后表y在跟表x关联时,不仅要关联之前的关联键,还要关联CAST(rand() * 5 + 1 AS INT) = 表z的number,这样就能起到打散的作用了。

聚合倾斜的解决方案一般有以下几种:
1)设置 set hive.groupby.skewindata=true。具体的处理方式是通过将倾斜的键进行拆分,生成多个子键(比如在原始键值的后面加上随机数1-5),然后将这些子键映射到不同的Reducer上进行处理。这样可以将原本倾斜的数据分散到多个Reducer上,减轻了单个Reducer的负载,实现了负载均衡。在计算结果返回之前,还需要通过合并子键的结果来得到最终的计算结果。相当于是做了两次groupby,先是带上随机数的预聚合,再是去掉随机数的最终聚合。

2)尽量少用count(distinct),采用先groupby再count的方式。groupby的时候如果还倾斜,就采用1)的方法进行处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值