一、数据倾斜原理
join实现原理
sql = select name, orderid
from user t1
join order t2
on t1.uid=t2.uid
group by 实现原理
sql = select rank, isonline, count(1)
from city
group by 1, 2
数据倾斜出现原因
1、对于join过程来说,如果出项较多的key值为空或异常的记录,或key值分布不均匀,就容易出现数据倾斜,
2、对于group by 过程来说,如果某一个key值有特别的多的记录,其它key值的记录比较少,也容易出项数据倾斜。
二、数据倾斜的解决方案
join引起数据倾斜的解决方法
1、如果是由于key值为空或为异常记录,且这些记录不能被过滤掉的情况下,可以考虑给key赋一个随机值,将这些值分散到不同的reduce进行处理。
2、如果是一个大表和一个小表join的话,可以考虑使用mapjoin来避免数据倾斜,mapjoin的具体过程如下。分为两步:
1) 通过mapreduce local task, 扫描小表,生成为一个hashtable文件, 并上传到distributed cache
2) 在map阶段,每个mapper, 从distributed cache中读取hashtable文件,扫描大表,并直接在map端join
3)在key值都为有效值时,还可以通过设置每个reduce处理的数据量的大小来处理数据倾斜,即:
set hive.exec.reducers.bytes.per.reducer = 1000000000或
set mapred.reduce.tasks=800 这两个一般不同时使用,
另外,还可以设置下面两个参数:
set hive.optimize.skewjoin = true;
set hive.skewjoin.key = skew_key_threshold (default = 100000)
可以就按官方默认的1个reduce 只处理1G 的算法,那么skew_key_threshold= 1G/平均行长.或者默认直接设成250000000 (差不多算平均行长4个字节)
group by 引起数据倾斜的解决方法
set hive.map.aggr=true,开启map之后使用combiner,这样基本上是对各记录比较同质的数据效果比较好,相反,则没有什么意义。通用的做法是设置下面两个参数:
set hive.groupby.mapaggr.checkinterval = 100000 (默认)执行聚合的条数
set hive.map.aggr.hash.min.reduction=0.5(默认)如果hash表的容量与输入行数之比超过这个数,那么map端的hash聚合将被关闭,默认是0.5,设置为1可以保证hash聚合永不被关闭;
还有一个是set hive.groupby.skewindata=true, 这个只针对单列有效。