hive的数据倾斜
1 产生操作
表连接:Join on a.id=b.id
分组计算:Group by
去重统计:Count Distinct count(group by)
原因
key分布不均导致的
人为的建表疏忽
业务数据特点
症状和表现
任务进度长时间维持在99%(或100%),查看任务监控页面(服务器ip:8088,查看running和finish两个界面),发现只有少量(1个或几个)reduce子任务未完成。
查看未完成的子任务,可以看到本地读写数据量积累非常大,通常超过10GB可以认定为发生数据倾斜(未完成的任务里面,还有超过10个G的数据没有跑完)。
倾斜度
- 平均记录数超过50w且最大记录数是超过平均记录数的4倍。
- 最长时长比平均时长超过4分钟;最大时长超过平均时长的2倍。
万能方法
set hive.groupby.skewindata=true;
对异常值赋予随机变量来分散key,可以通过rand函数将为null的值分散到不同的值上
case when uid is null then cast(rand(100)*100000 as int) else uid end
nvl(uid, cast(rand(100)*100000 as int))
将异常值单独拿出来处理,最后union回去
set hive.groupby.skewindata = true; – 数据倾斜进行负载均衡
(默认是false, group by过程出现倾斜)
set hive.optimize.skewjoin=true; – join 过程出现倾斜 应该设置为true
count distinct拆成两个job,先distinct,再对子表count(1)(数据量大)
with t1 as
(select distinct *
from
(
select user_id,order_id from orders where order_dow=‘1’
union all
select user_id,order_id from orders where order_dow=‘2’
union all
select user_id,order_id from orders where order_dow=‘3’
) t
)
select count(*) from t1;
2、数据倾斜-大小表关联
原因
Hive在进行join时,按照join的key进行分发,而在join左边的表的数据会首先读入内存,如果左边表的key相对分散,读入内存的数据会比较小,join任务执行会比较快;而如果左边的表key比较集中,而这张表的数据量很大,那么数据倾斜就会比较严重,而如果这张表是小表,则还是应该把这张表放在join左边。
思路
将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率使用map join让小的维度表先进内存。
方法
- Small_table join big_table
- select /*+ mapjoin(small_table) */ * from big_table join small_table
当表格的数据量差异实在是太大的时候:例如三个表格进行表连接,一个表格是20亿行,一个是1亿行,一个是100万行,这个时候只能拆分大的表格,将大表拆分成N个差异不是特别大的表。
create table a as select * from table limit 0,200000000;