hive数据倾斜

hive数据倾斜

1. join时产生数据倾斜

1.1 小表join大表

使用mapjoin,左边小表,右边大表,在map端进行join,把小表放到了内存,然后扫描大表进行join.没有shuffle,不走reduce.
开启参数:

set hive.auto.convert.join = true0.11版本后默认是true)
set hive.mapjoin.smalltable.filesize=25000000(设置小表的大小,默认就是25M)

1.2 大表join大表

1.2.1 key为空值造成的影响

空值太多join时,会把所有key为空值的数据发送到同一个reduce中,发生数据倾斜

解决方法:

  • 空值不重要的情况,先把空值过滤掉,在进行join
select * from logs
join user 
on logs.uid is not null and logs.uid=user.uid;
  • 空值不能过滤,使用case when 对空值附上随机值,然后进行join,这样会把所有key为空值的数据发送到不同的reduce中去处理.
select
*
from logs
left join user
on case when logs.uid is null then concat('',round(rand()*1000)) else logs.uid=user.uid;

1.2.2 热点key

可以将热点数据和非热点数据分别进行处理,最后再合并到一起.

1.3 不同数据类型join

比如log表中的uid类型为int,也有string类型.user表中的uid类型为string.

<1>解决

将log表中uid为int类型的数据转换成string,然后进行join

select
*
from log
join user
on cast(log.uid as string)=user.uid;

2. group by 产生数据倾斜

2.1 开启数据倾斜的负载均衡

默认为false,改为true

set hive.groupby.skewindata=true;

任务执行的时候会有两个mr,

第一个mr任务会把map输出的结果集合随机分配到所有reduce中,做部分聚合;

第二个mr任务会根据预处理的结果按照 group by key 分布到reduce中,完成最终的聚合操作.

2.2 两阶段聚合(给分组key拼接随机数聚合一次,去除随机数再聚合一次)

产生的原因:
key.hashcode()%numReduce 值相同的就分到了同一个reduce中

当某个分组key数据特别大的时候 group by 阶段就会发生数据倾斜.

原始Hql:

select
works,
count(1) as user_cts
from other
group by works;

<1>解决

给原分组key添加随机数聚合一次,然后再去掉随机数再聚合一次

通过控制给key拼接上的随机数的大小范围来控制热点key分发到不同reduce的范围

SELECT
split(t.total)[0] as works,
sum(t.cts) as user_cts
FROM
(
   SELECT
   CONCAT(works,'_',ROUND(RAND()*1000)) as total,
   count(1) as cts
   from other group by CONCAT(works,'_',ROUND(RAND()*1000))
) t
group by split(total,'_')[0];

你可能感兴趣的:(hive,hive,sql)