赞
踩
map100%,reduce一直卡在一个值,如99%。
数据按key的hash值分配到reduce中,如果有的key值比较集中,就会导致某个或某些reduce分配的数据量太大,这样当其他reduce运行完毕,分配数据量过大的reduce仍在运行,导致reduce进度一直卡着不动,这种现象被称为数据倾斜。造成数据倾斜的根本原因就是key值分布不均匀。
join、group by、Count Distinct
1.groupby、count distinct数据倾斜:
hive.map.aggr = true
hive.groupby.skewindata=true
有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Key 分布到 Reduce 中(这个过程可以保证相同的 Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
2.join 的数据倾斜:
hive.optimize.skewjoin=true;
如果join过程中出现了数据倾斜,应该设置为true
set hive.skewjoin.key=100000;
这个是join的键对应的记录条数超过这个值则会进行优化,优化措施:正常是只有一个job的,优化后会有两个job。当倾斜Key值达到100000以上的时候,hive会把不倾斜的key进行join,倾斜的 key 的数据将会被写入HDFS临时文件,hive会再启动一个job,然后将倾斜的数据进行map 端join,最终将两个结果合并。
但是这种处理方式不是所有地方都有效。
select count(1) from (select user_id from log group by user_id) t;
来替换count(distinct)完成计算。
1.把空值单独处理,再与其他值的处理结果进行uinon all.
2.把空值的key变为随机数。
select *
from log a
left join users b
on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;
方法2比方法1效率更好,不但io少了,而且作业数也少了。解决方法1中 log读取两次,jobs是2。解决方法2 job数是1 。这个优化适合无效 id (比如 -99 , ’’, null 等) 产生的倾斜问题。把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。
类型转换过程中可能会出现转换失败,比较常见的是string转int,失败后会造成大量null值,进而流入同一个reduce,导致数据倾斜。
处理办法就是在条件中进行类型转换,保证两端数据类型一致。
Map端join会使所有的 maptask 节点都装载小表 b 的所有数据,然后大表 a 的 一个数据块数据比如说是 a1 去跟 b 全量数据做链接。实现方法:
select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;
在 hive0.11 版本以后会自动开启 map join 优化,由两个参数控制:
set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启
set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化
可以根据业务逻辑,只取必要数据(行、列两个维度限制),尽量减小数据大小,使之成为小表。比如:
当分析某段时间的日志表logs数据是亿级的,用户表users数目有数十万,把users当小表做map join会超出内存时,我们可以把users行数减少到只取出logs中包含的users,然后进行列裁剪,这样可能大大缩减users所占空间,从而可以实现map join。
select /*+mapjoin(t1)*/* from log t1
left outer join (
select /*+mapjoin(t11)*/ d.*
from ( select distinct user_id from log ) t11 join users t12 on t11.user_id = t12.user_id
) t1
on t0.user_id = t1.user_id;
两个Hive表进行join的时候,如果数据量都比较大,那么此时可以看一下两个Hive表中的key分布情况。
方案实现思路:
方案优点:对于join导致的数据倾斜,如果只是某几个key导致了倾斜,采用该方式可以用最有效的方式打散key进行join。而且只需要针对少数倾斜key对应的数据进行扩容n倍,不需要对全量数据进行扩容。避免了占用过多内存。
方案缺点:如果导致倾斜的key特别多的话,比如成千上万个key都导致数据倾斜,那么这种方式也不适合。
方案二:分桶join+map join
参见:https://blog.csdn.net/Samaritan_H/article/details/79090103
方案一:我们可以按6.1的方式对倾斜表所有数据加上n以随机前缀,对另一张表进行全表数据膨胀操作,然后进行关联。
这样可以缓解数据倾斜问题。但是比较消耗内存资源。
方案二:依旧分离出比较集中的key值记录,另一张表也取出相应的key值记录,然后开启map join进行关联操作,对结果进行uion。
方案三:分桶join+map join
参考文献:https://blog.csdn.net/jin6872115/article/details/79878391
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。