Hive倾斜—不患寡而患不均
一、数据倾斜的原因
Hive倾斜的原因很大部分是由于sql中的join语句与group by语句。
原因:对于普通的join操作,会在map端根据key的hash值,shuffle到某一个reduce上去,在reduce端做join连接操作,内存中缓存join左边的表,遍历右边的表,依次做join操作。所以在做join操作时候,将数据量多的表放在join的右边。
当数据量比较大,并且key分布不均匀,大量的key都shuffle到一个reduce上了,就出现了数据的倾斜。
二、数据倾斜的现象
map/reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完,此称之为数据倾斜。
hive在跑数据时经常会出现数据倾斜的情况,使的作业经常reduce完成在99%后一直卡住,最后的1%花了几个小时都没跑完,这种情况就很可能是数据倾斜的原因。
举例:
比如当某个购物网站一天内按照城市ID来区分的话,ID为1的城市一天卖出去10W个商品,ID为2的卖出去200个商品,ID为3的卖出去50个商品。
Table A的数据含有城市ID、城市名,table B的数据含有城市ID、订单号排序(分别为0-100000(订单100000个)、100000-100200(订单200个)、100200-100250(订单50个))。
当我们用join语法的时候key值应该为1、2、0,因此reduce=0的join会处理10W数据,其他的为200、50。这会造成数据倾斜。
当我们用group by语法与join类似。
三、数据倾斜的优化
1.如果是join 过程中出现倾斜应将此项设置为true。
hive.optimize.skewjoin.compiletime=true;
不影响结果可以考虑过滤空值
<property>
<name>hive.optimize.skewjoin.compiletime</name>
<value>false</value>
</property>
join(数据倾斜)
在进行两个表join的过程中,由于hive都是从左向右执行,要注意讲小表在前,大表在后(小表会先进行缓存)。
2、如果是group by过程出现倾斜应将此项设置true。
hive.groupby.skewindata=true;
<property>
<name>hive.groupby.skewindata</name>
<value>false</value>
<description>Whether there is skew in data to optimize group byqueries</description>
</property>
问题:为什么默认为false?
因为开启为true后,会至少开启两个MapReduce,执行时间比开启一个长,因此最好出现数据倾斜之后在开启。
hive.optimize.skewjoin.compiletime=true; 如果是join过程出现倾斜应该设置为true
此时会将join语句转化为两个mapreduce任务,第一个会给jion字段加随机散列
set hive.skewjoin.key=100000; 这个是join的键对应的记录条数超过这个值则会进行优化。