数据倾斜问题(Hive)


6大倾斜问题清单

  1. NULL值导致的数据倾斜
  2. 大文件不可拆分导致的数据倾斜
  3. 小表JOIN大表导致的数据倾斜
  4. 统一字段不同数据类型导致的数据倾斜
  5. 确实无法减少数据量导致的数据倾斜
  6. 数据膨胀导致的数据倾斜

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内存。

参考资料


文章作者: tzkTangXS
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 tzkTangXS !
  目录