hive数据倾斜的解决方案

分布式文件系统HDFS可以存储海量的数据(以T为单位的数据量),分布式计算框架MapReduce可以对存储在HDFS的数据进行处理后再将结果写回到HDFS。MapReduce + HDFS可以完成对海量数据的批量处理,但是这套组合会导致很多重复性的工作,有些处理起来比较繁琐,例如从文件中选取特定行数的数据,按照某些字段对数据进行排序,统计某些字段出现的字数,将多个数据源的数据join在一起。Hive的出现很好的解决了以上问题,用创建表的方式定义分布式文件中数据的meta信息后,用户可以使用像在关系型数据库中经常使用的SQL语句对这些数据进行操作,实际上Hive将这些SQL语句转化为了对应的MapReduce任务。

在Hive使用到最多的操作就是将多个表中的数据join到一个表中,例如:

1
SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)

有时在join的过程中会碰到join的两个表的数据太大,导致join过程很慢且失败。此时一般有3种解决方案:

  • 增加Reducer的数量,使得各个Reducer上的数据量不会超过最大限制。
1
2
3
set mapred.reduce.tasks=500;
 
SELECT a.*,b.name FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
  • 有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。例如key对应的字段为空
1
2
3
4
5
6
7
SELECT table_a.* , b.name
FROM
(
   SELECT *
   FROM a
   WHERE id is not null
)table_a JOIN b ON (table_a.id = b.id AND table_a.department = b.department)
  • 有的时候虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的reducer上。例如:
1
2
3
4
5
6
SELECT table_a.* , b.name
FROM
(
   SELECT when is id null or id=0 then cast(rand(10) * -1000000 as int) as id, gender
   FROM a
)table_a JOIN b ON (table_a.id = b.id AND table_a.department = b.department

你可能感兴趣的:(Hive,MR)