6大倾斜问题清单
- NULL值导致的数据倾斜
- 大文件不可拆分导致的数据倾斜
- 小表JOIN大表导致的数据倾斜
- 统一字段不同数据类型导致的数据倾斜
- 确实无法减少数据量导致的数据倾斜
- 数据膨胀导致的数据倾斜
1. 空值导致的数据倾斜
原因:
key值为NULL,它们的hash值相同,被分配给同一个reduce导致的数据倾斜。
解决方案:
1. 不让空值数据参与JOIN
select a.*,b.*
from a
left join b on a.key is not null and a.key = b.key
union all a where a.key is null
2. 将空值后面加上随机数
select a.*,b.*
from a
left join b
on
case
-- when a.key is null then concat('tzk',',',rand())
when a.key is null then concat_ws(',','tzk',rand())
else a.key
end = b.key
2.大文件不可拆分导致的数据倾斜
原因:
文件过大,且压缩格式采用的是不可分割的格式比如Gzip
解决方案:
换一种压缩方案如:bzip2,Zip
3. 表链接时引发的数据倾斜
原因:
某一张表的某一个Key数据倾斜严重。从而导致大量这个key值的数据在一个reduce中执行。
解决方案:
(1)如果是大表join小表
采用MapJoin,将小表放到内存中,在Map阶段Join,每一个MapTask(MapTask的数量由切片决定)中的数据与小表join,避免了Reduce阶段,从而避免了数据倾斜。
hive.auto.convert.join=true 默认值为true,自动开启MAPJOIN优化。
hive.mapjoin.smalltable.filesize=2500000
select a.*,b.*
from a
join b on a.key =b.key
edit:
将表放到Map端内存时,如果节点的内存很大,但还是出现内存溢出的情况,我们可以通过这个参数 mapreduce.map.memory.mb 调节Map端内存的大小。
(1)大表join大表
同空值的处理类似,将导致数据倾斜的Key加上随机数。
-- 加入a.key== 大海时,数据占比40%
select *
from a
left join b on
case a.key
when '大海' then concat_ws('_',a.key,rand())
else a.key
end = b.key
4. 同一字段不通类型导致的数据倾斜
4.1 原因:
a表的key值类型为String或者int型,而b表则为int型。那么默认按照int,那么所有的String类型会被分配到同一个reduce导致数据倾斜。
4.2 解决方案:
统一数据类型,将Int转换为String。
Select *
from a
left join b
on cast(a.user_id as String) = cast(b.user_id as String)
5. 确实无法减少数据量引发的数据倾斜
5.1 原因:
在一些操作中,我们无法减少同一个reduce处理的数据量。
select p.id,p.province_name,collect_list(o.final_amount)
from dwd_order_info o
right join dim_base_province p
on o.province_id = p.id
group by p.id,p.province_name
5.2 解决方案:
通过mapreduce.reduce.memory.mb这个参数增加reduce内存。