文章目录
- Hive的数据倾斜
- 数据倾斜是什么?
- 主要表现
- 产生数据倾斜的原因
- 空值产生的数据倾斜
- key分布不均匀
- 大小表关联产生数据倾斜
- 大表大表关联
Hive的数据倾斜
数据倾斜是什么?
顾名思义,就是数据分布不均匀,某个节点数据大量集中,而另外的节点数据量却很少。
主要表现
一个节点的任务很快就跑完了,而另外一个节点的任务很久迟迟不结束,这就是典型的数据分布不均匀。
产生数据倾斜的原因
1、key 分布不均匀
2、业务数据本身的特性
3、建表考虑不周全
4、某些HQL语句本身就存在数据倾斜
空值产生的数据倾斜
以一张表为例(数据已经进入各个节点)
这张表里gender列存在一些空值,根据HashPartition,会有三种数据分配到三个节点。
这个时候解决办法是:
1、可以选择先将没有null值得两张表先join,最后再union all 有空值的表,将空值连接到最下面。
user_id 为空的不参与关联
select * from log a join user b on a.user_id is not null and a.user_id = b.user_id
2、补全空值(数值符合高斯分布)
可以将空值赋予一个字符串加一个随机值,例如concat('hive',rand()),这样可以将空值打散
ps:如果说是age这列存在空值,可以采取中位数的方式,一般来说,数据符合高斯分布,说白了就是正态分布,也就是在最小值和最大值之间徘徊,所以可以取中位数。数据符合高斯分布,也就认为数据是可靠的。
或者说可以根据实际考察结果根据男女比率来填充null值,这样的数据是符合高斯分布的,也就认为是可靠的。
key分布不均匀
一种数据过多,一种数据过少且数据还没有打散进入各个节点,可以加盐打散分散到各个节点。
以下表为例,可以在gender后加上一个随机数再hash就可以打散分散到各个节点。
或者可以将age+gender合并成一列再hash,然后分散到各个节点
大小表关联产生数据倾斜
解决方法:使用map join(只支持inner join)
因为数据交互的过程中存在shuffle,就像需要两张表join的时候,需要数据就拉取数据,必然存在数据交换,但是将小表作为内存存在每个节点上,自己的数据和自己关联不存在shuffle这一说法
在低版本中,就是hive0.11版本之前,强制两张表关联,就是将小表发到 各自节点上,目前高版本中,开启map join,默认是开启的
0.11版本之前
强制执行map join
select /*+mapjoin(表名)*/ #将小表强制放入内存
from t1 join t2 on t1.field1=t2.field;
高版本:默认开启
set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启
set hive.mapjoin.smalltable.filesize=25,000,000 //设置小表不超过多大时开启 mapjoin 优化
大表大表关联
解决方法:将大表切分成小表,然后再分别map join