一.join操作数据倾斜
1.mapjoin
map join 默认开启
set hive.auto.convert.join = true(0.11版本后默认是true)
set hive.mapjoin.smalltable.filesize=25000000(设置小表的大小,默认就是25M)
不管大小表放左边还是右边,自动将小表放入内存,然后在map端顺序扫描大表跟内存中的数据进行join,没有reduce阶段,没有shuffle
2.类型不一致
关联字段不一致引发的数据倾斜操作有一个a表关联字段是string类型,b表关联字段是bigint类型,将bigint转换为string类型就可以了
select
a.guid,
a.oid,
b.name
from a
join b
on a.guid=cast(b.guid as string)
3.特殊值过多
如null,空,0导致的数据倾斜 可以将特殊值加盐,可以打散到多个reduce中
select
b.guid,
a.oid,
b.name
from a
join b
on (case when a.guid is null or a.guid=0 or a.guid='null' then CONCAT('hive',RAND()) else a.guid end) = b.guid
4.大表join大表skewjoin
综合以上几点,先进行 行列过滤,然后有特殊值将特殊值加盐,类型不一致的类型转换一致 除此之外,还可以skewjoin开启join倾斜优化参数
set hive.optimize.skewjoin=true;
set hive.skewjoin.key=100000;
hive 在运行的时候没有办法判断哪个key 会产生多大的倾斜,所以使用这个参数控制倾斜的阈值,如果超过这个值,新的值会发送给那些还没有达到的reduce, 一般可以设置成你处理的(总记录数/reduce个数)的2-4倍都可以接受
原理:
对于skewjoin.key,在执行job时,将它们存入临时的HDFS目录,其它数据正常执行;
对倾斜数据开启map join操作,对非倾斜值采取普通join操作;
将倾斜数据集和非倾斜数据及进行合并操作。
5.简单的增加 reduce 并行个数
set mapred.reduce.tasks=100;
二.group by操作数据倾斜
1.map端聚合
在map端部分聚合,然后在reduce端全局聚合
set hive.map.aggr = true;
2.开启group by负载均衡参数,会分两阶段聚合
原理如3
set hive.groupby.skewindata=true;
3.在sql中给group by的key加盐
在sql中给group by的key加盐,将key打散到多个reduce中 先聚合一次,然后将第一阶段的结果中key去除随机数,然后再总的聚合.明显第一阶段使相同的key都打散到了多个reduce中,并且拉去到 第二阶段reduce中的数据明显减少,这就是两阶段聚合.
select
user_id,
sum(cts) as s_cts
from
(
select
user_id,
round(rand()*1000) as rk,
count(1) as cts
from group_t
group by user_id,round(rand()*1000)
) t1
group by user_id
4.避免count(distinct)操作
count(distinct)操作是用一个reduce来完成的,如果数据量很大,会导致整个job很难完成
使用sum() group by 代替
|