现在常见的数据倾斜分两种情况,一种是大量的空值导致的,另一种是一对多的情况造成的,下面分别说一下这两种的解决方案。
1.空值
这种情况下比较好解决,有两种解决方式,使用哪一种具体取决于你需不需要主键为空值的该行纪录的其它信息,因为有些时候这些信息也有用处。
下面是伪代码:
1.这种情况在join的时候直接过滤空值,最后给union all上
select * from a join b on a.id is not null and a.id = b.id
union all
select * from a where a.id is null;
2.给空值字段取一个字符串常量+随机数
select * from a left outer join b on
case when a.id is null then concat('常量字段',rand()) else a.id end = b.id
个人比较推荐第二种方法,因为其不但 IO 少了,而且作业数也少了,方案 1 中,log 表 读了两次,jobs 肯定是 2,而方案 2 是 1。这个优化适合无效 id产生的数据倾斜,把空值的 key 变成一个字符串加上一个随机数,就能把造成数据倾斜的 数据分到不同的 reduce 上解决数据倾斜的问题。使本身为 null 的所有记录不会拥挤在同一个 reduceTask 了,会由于有替代的 随机字符串值,而分散到了多个 reduceTask 中了,由于 null 值关联不上,处理后并不影响最终