Hive数据倾斜问题

什么是数据倾斜

MapReduce中,相同Key的Value都给了一个reduce,如果个别key数据较多,而其他key的较少,就出现了数据倾斜。有的map很快,有的reduce很慢。Hive执行是分阶段的.Map的处理数据量差异取决于上一个stage的reduce输出,如果在map端,有的job很快,有的很慢,就出现了数据倾斜。

数据倾斜的情况

1)连接join: a)小表与大表,小表key集中。分发到一个或几个的reduce上的数据远高于平均值。b)大表与大表,0值或者空值太多。空值都由一个reduce处理。2)分组:groupby维度过小,某值的数据过多。 3)去重:distinct/count 处理特殊值的reduce耗时太长。

Hive数据倾斜问题

解决方法

参数调节

1 Hive.map.aggr=true;

在map端做聚合操作,相当于combiner。

2 Hive.groupby.skewindata=true;

Hive在进行groupby时候,会讲相同的key分配到同一个reduce中。当设置为true后,map端输出的相同key会被随机分配到不同的reduce中,在每个reduce中做一个部分聚合,这是第一个MR job。然后再将第一个job处理后的结果通过key分配到reduce中,得到最终的聚合操作,这便是第二个MR job。

sql语句调节

1 驱动表选择:选用key分布最均匀的表作为驱动表;

2 大小表join:使用map join

map join原理:

a.task1将小表A转为为一个HashTable结构,写入到本地文件中。

b.task2启动MR,扫描大表B,根据B的每一条记录去和本地的A对应的HashTable做关联,输出结果;task2相当于一个没有reduce 的MR任务

c.有多少个Map Task就有多少个结果文件。

一般情况下用的join 是一个common join,map join相当于common join的优化,省去了shuffle和reduce,故map join是一个没有reduce的MR任务。可以通过hive.auto.convert.join=true(版本0.7+)设置;

小表一般不小于1G,推荐使用map join,否则common join;

3 count(distinct)

count(distinct)只有一个reduce任务,若表中存在大量key为空的值,可以直接将空值去掉,最后结果+1;如果还需要作其他处理,则可将空值单独拿出来分析;

可以用sum() group by 代替 count(distinct) 或者 设置 Hive.groupby.skewindata=true;