数据倾斜通常指hive根据key值hash分发到各个节点,相同的key值会分发到一个执行节点中,由于某些key值对应的数据量比其它key值的数据量大很多,导致某些执行节点的运行时间远大于其它节点,从而导致整个job执行时间较长。
在hive中执行的sql会有map和reduce两个阶段,map阶段的数据倾斜主要为数据从磁盘读入内存时、join,reduce阶段数据倾斜主要有join、group by、count distinct,针对于这些操作有不同的处理方式来避免数据倾斜。
一、map阶段
1.由于map读入数据的文件大小分布不均匀,并且小文件特别多,导致某些map读取并处理的数据特别多
这种情况可通过参数调整防止由于小文件过多导致每个map读取的数据量不均匀,mapred.max.split.size=256000000(每个map可以处理的最大文件大小,可调大该值来减少map数)
二、reduce阶段
1.join
数据表在进行join时有两种情况会出现倾斜:
(1)小表和大表join的倾斜
这种情况,可以直接使用hint(如/ + mapjoin(a) /)将小表全部加载到内存中后顺序扫描大表完成join(mapjoin有使用限制,必须是join中的从表较小时才可用,从表主要指left join中的右表,right join中的左表,小表最大为2GB)
(2)大表和大表join的倾斜
这种情况,需要具体原因具体分析:
- 由某些特殊值引起的数据倾斜
参数设置方式:hive.optimize.skewjoin=true; 将造成倾斜的特殊值先不处理直接写入hdfs,然后新启一个mapjoin专门处理特殊值;可以通过参数设置数据量超过多少默认为特殊值,如hive.skewjoin.key=10000,表名超过10000条的key会被认定为特殊值;
特殊值的处理也可以在sql中进行优化,在sql中将特殊值与非特殊值分别处理,然后再通过union all拼接,但这样会增加IO; - 由空值引起的数据倾斜
将空值的key变为一个字符串加上随机数,也可以借鉴特殊值的sql优化方式; - 不同数据类型关联产生的数据倾斜
如int型的用户id与string类型的用户id进行关联,hive默认会将hash按int类型分配,string类型的数据会全部分配到一个reduce中,此时应将int型转化为string再做关联
2.group by + count distinct
当sql中出现这种情况时,需预先对group by的字段进行去重处理,然后再进行count
原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/191377.html