A表:单副本14.9G,1002354875条数据
B表:单副本1.5G,40102307条数据
两个表通过partition_path字符串去full outer join关联,没有优化前执行要88分钟
第一种优化:
在sql结尾使用distribute by rand() ,reduce个数88个,但是还是有数据倾斜
select * from A full outer join B
on a.partition_path =b.join_path
distribute by rand()
第二种优化:
经过日志查看数据倾斜的key是 tmp.db,于是思考将这个数据不进行join关联,并将倾斜的key打散,但是发现不加distribute by rand() ,reduce个数只有1个,还是数据倾斜,于是加上distribute by rand() 后,reduce变87个,最后执行效果是 20分钟
select * from A full outer join B
on (case when a.partition_path<>'hdfs://ns6/hive/dmr/dmr_tmp.db' then a.partition_path else cast(ceiling(rand() * -65535) as string) end ) =b.join_path
distribute by rand()
第三种优化:
设置参数
==============
数据倾斜总结
原因一:关联字段中有空值或者脏数据,
原因二:关联字段中key都为有效值是,某些key量大,造成reduce计算量大
原因三:由于group by 中某个key值较大引起的
解决办法:
原因一:
如果不能过滤,则将这部分给key赋予随机值,交给不同的reduce处理
例如 cast(ceiling(rand() * -65535) as string) end )
原因二:
1、如果大小表join,则使用mapjoin,将小表放入缓存中,广播的方式分发到不同的map中,与大表在map端进行join。
2、设置reduce个数参数,提高reduce个数
set mapred.reduce.tasks=800
或者
set hive.exec.reducers.bytes.per.reducer = 1000000000 #每个reduce处理的数据量
3、设置数据倾斜参数
set hive.optimize.skewjoin = true;
set hive.skewjoin.key = skew_key_threshold (default = 100000)
原因三:
1、设置在map端进行combiner聚合,但是这个通常对数据比较同质的有用,
set hive.map.aggr=true
2、设置每个reduce聚合的条数
set hive.groupby.mapaggr.checkinterval = 100000 (默认)执行聚合的条数
3、使用map端的hash聚合,如果hash表的容量与输入行数之比超过这个数,那么map端的hash聚合将被关闭,默认是0.5,设置为1可以保证hash聚合永不被关闭
set hive.map.aggr.hash.min.reduction=0.
4、针对单列聚合有效的参数
set hive.groupby.skewindata=true