(1)数据倾斜长啥样
(2)怎么产生的数据倾斜
①不同数据类型关联产生数据倾斜
情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的join操作时。
后果:处理此特殊值的reduce耗时;只有一个reduce任务。默认的hash操作会按int类型的id来进行分配,这样会导致所有string类型id的记录都分配到一个reducer中。
解决方式:把数字类型转换成int类型
select * from users a
left outer join logs b
on a.user_id = cast(b.user_id as string)
bug记录:https://www.jianshu.com/p/2181e00d74dc
②控制空值分布
在生产环境经常会用大量空值数据进入到一个reduce中去,导致数据倾斜
解决办法:
自定义分区,将为空的key转变为字符串加随机数或者纯随机数,将因空值而造成倾斜的数据分布到多个reducer。
注意:对弈异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少
(3)解决数据倾斜的方法:主要是两类(单表和多表关联)
单表:
JOIN ON关联字段:
-------------------------以上述为准!!!!------------------------------------
①group by
注:group by优于distinct group
解决方式:采用sum() group by的方式来替换count(distinct)完成计算
②开启MapJoin
③开启数据倾斜时负载均衡
set hive.groupby.skewindata=true;
思想:就是先随机分发并处理,再按照key group by来分发处理
操作:当选项设定为true,生成的查询计划会有两个MRJob
第一个MRJob中,Map的输出结果集合会随机分布到reduce中,每个reduce做部分聚合操作,并输出结果,这样处理的结果是相同的groupby key有可能被分发到不同的reduce中,从而达到负载均衡的目的;
第二个MRJob中,再根据预处理的数据结果按照groupby key分布到reduce中(这个过程可以保证相同的原始groupby key被分布到同一个reduce中),最后完成最终的聚合操作
点评:它使计算变成了两个MapReduce,先在第一个中在shuffle过程partition时随机给key打标记,使每个key随机均匀分配到各个reduce上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上。
所以需要第二次的MapReduce,这次就回归正常shuffle,但是数据分布不均匀的问题在第一次MapReduce已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次MR中随机分布到各个节点完成