最近做宽表,insert overwrite table … select
导入数据时,发生了数据倾斜

情况

通过ui界面看到,有一半的数据,都跑在了单个节点上,执行的时候,报错,11.3G超出物理内存限制的11G。
百度搜了一下,hive数据倾斜,全部都是复制粘贴。。。
内容都是那几句,空值过滤,设置mapjoin,负载均衡,空值时随机数分配,预聚合,上面该操作的,我都操作过了,依然无法解决

排查–引起数据倾斜的key

我的解决方案是,首先找出产生数据倾斜的key值,在sparkUI界面上,看执行情况,可以判断出在哪一个stage时,产生了数据倾斜。然后 explain sql语句。

可以看到sql的执行过程,例如在ui界面上看到stage 6 发生了数据倾斜。

hive一张表条数SAMPLE hive只显示十条数据_mapreduce


stage 0 对应的是 reduer 10,按照顺序 stage 6 对应的是 reducer 20,然后到reducer 20 的位置去,具体查看,该过程对应的是那条sql语句,从而判断出倾斜的key值。发现spu_id = 0是 占了一半的数据,是由于公司在表设计的时候,分spu_id = 0 和 spu_id != 0 两种情况。

解决

1.针对这种情况,常用的解决是开启mapjoin
而mapjoin,针对的是大表join小表的情况,如果大表中有一半的数据量是几个key,数据倾斜,mapjoin是将小表放入缓存中,然后大表一点点读取运行完毕。
开启mapjoin,由于hive版本,或者hive的运行引擎不同,有点区别
(1)如果是hive本身mr版本 加上 /+mapjoin(f)/
(2)本公司是spark引擎 使用了两个参数去调优
set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=25000000;

但是如果小表数据量也比较大,无法全部放入缓存中,即使你设置了mapjoin也没法解决,这种情况使用下面方法
2.大表join大表,使用随机数解决倾斜
举例:
例如key=0的值占了表的一半
将带有key=0的数据单独拎出来,然后将其添加随机数,本例中将表拆分10份,与另张表做join

#数据膨胀
select * from table a  left join table2 b on a.key = b.key
改为 
select * from table a 
where a.key != 0
left join table2 b 
on a.key = b.key
union all
select *,concat(celling(rand()*10,a.key) key from table a 
where a.key = 0
left join 
(select concat('1',key) key from table2
union all  
select concat('2',key) key from table2
union all  
select concat('3',key) key from table2
union all  
select concat('4',key) key from table2
union all  
select concat('5',key) key from table2
union all  
select concat('6',key) key from table2
union all  
select concat('7',key) key from table2
union all  
select concat('8',key) key from table2
union all  
select concat('9',key) key from table2
union all  
select concat('10',key) key from table2) b
on a.key = b.key