文章来源:http://www.dcharm.com/?p=32
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)</pre>
|
- 有的时候虽然某个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)</pre>
|