场景:
我有接近7亿条网站访问浏览数据要做一次 按 host(域名) 分区,访问时间进行排序(取最先访问) 说白了就是row_number over(partition by host order by ftime)。 突然发现会报错:
FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
现象就是 reduce 99% 快一个小时,一直99%
这时候你要知道,你很可能遇到了数据倾斜的场景了。
方法一:
查看执行计划
explain 你的sql
例如:
说白了就是map 端有key ,reduce 也有key
你需要设置一些参数在map端 先聚合,这样key到reduce 分组的时候压力少点。
设置参数:
set hive.groupby.skewindata=true;
set hive.map.aggr=true;
set hive.vectorized.execution.enabled=true;
set hive.vectorized.execution.reduce.enabled = true;
set hive.exec.compress.output=true;
前两个分别是 reduce 和map 的调优,
hive.groupby.skewindata=true 有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
set hive.map.aggr=true;
map端的提高聚合性能。
后面三个是向量计算和输出压缩。
这样如果没解决了的话可以尝试对key进行随机赋值,相当于Java自定义partition 的过程。
select case when userid is null then cast ( rand ( 47 )* 100000 as i nt )
我没怎么用过。
最后我做了host 的分组统计,观察了数据分布。发现前二的log数量 host 总量占2/7,于是我放弃了Top2的计算,这样能顺利
跑出结果了。然后对top2进行统计。在union all 一下 之前的结果。特殊数据特殊对待。
适用场景: 数据倾斜字段稳定,长期。
业务上可变通。