调优Hive查询性能

13

我有一个Hive查询,选择了约30列和大约400,000条记录,并将它们插入到另一个表中。我的SQL语句中有一个内部连接。

这个查询失败了,因为Java的GC超时限制被超过了。

奇怪的是,如果我删除连接子句,只从表中选择数据(稍微高一点的数据量),那么查询就能正常工作。

我对Hive不太熟悉。我不明白为什么这个连接会导致内存异常。

在编写Hive查询时,是否有什么需要注意的地方,以避免出现这些问题? 有人能解释一下为什么连接可能会引起这个问题,而选择相同数量的列、更大的数据量却不会呢?

感谢您对此的想法。 谢谢

2个回答

41
根据Hive的版本和您的配置,您的问题的答案可能会有所不同。如果您可以共享确切的查询以及两个表的创建语句和其大小的估计值,那将更容易。
为了更好地理解问题,让我们来看一下Hive中“常规”内连接的工作原理。 Hive中的连接(MapReduce): 以下是Hive中如何将内连接编译为MapReduce的简化描述。通常,如果您有两个名为t1和t2的表,并使用连接查询,例如:
SELECT
   t1.key, t1.value, t2.value
FROM
   t1
   JOIN
   t2 (ON t1.key = t2.key);

其中,t1具有以下内容:

k_1    v1_1
k_2    v1_2
k_3    v1_3    

其中,t2具有以下内容:

k_2    v2_2
k_3    v2_3
k_4    v2_4    

我们期望连接结果为:
k_2    v1_2    v2_2
k_3    v1_3    v2_3

假设表格存储在HDFS上,它们的内容将被拆分成文件片段。映射器将以文件片段作为输入,并将键作为表的键列发出,值作为表的值列和标志(表示记录来自哪个表,即t1或t2)的组合。
对于t1:
k_1, <v1_1, t1>
k_2, <v1_2, t1>
k_3, <v1_3, t1>
的内容:
k_2, <v2_2, t2>
k_3, <v2_3, t2>
k_4, <v2_4, t2>

现在,这些发出的记录经过洗牌阶段,在此阶段,具有相同键的所有记录将被分组并发送到减速器。每个reduce操作的上下文是一个键和一个包含与该键对应的所有值的列表。在实践中,一个减速器将执行多个reduce操作。
在上面的例子中,我们将得到以下分组:
k_1, <<v1_1, t1>>
k_2, <<v1_2, t1>, <v2_2, t2>>
k_3, <<v1_3, t1>, <v2_3, t2>>
k_4, <<v2_4, t2>>

在reducer中会对值列表中的每个值执行乘法,如果这些值对应不同的表,则会执行乘法。
对于k_1,来自t2的没有值,因此不会发出任何内容。
对于k_2,发出值的乘积-k_2,v1_2,v2_2(因为每个表都有一个值,1x1 = 1)。
对于k_3,发出值的乘积-k_3,v1_3,v2_3(因为每个表都有一个值,1x1 = 1)。
对于k_4,来自t1的没有值,因此不会发出任何内容。 因此,您将获得您从内部连接中期望的结果。
好的,那我该怎么做?
  1. 你的数据可能存在偏斜。换句话说,当reducer接收到数据时,与某个键相关的值列表非常长,导致错误。为了缓解这个问题,你可以尝试增加JVM可用内存。在hive-site.xml中将mapred.child.java.opts设置为像-Xmx512M这样的值即可。你可以通过在Hive shell中执行set mapred.child.java.opts;查询此参数的当前值。

  2. 你可以尝试使用“常规”连接的替代方法,例如map join。上述连接的解释适用于常规连接,在其中连接发生在reducers中。根据你使用的Hive版本,Hive可能能够自动将常规连接转换为更快的map join(因为连接发生在map阶段)。要启用优化,请将hive.auto.convert.join设置为true。该属性是在Hive 0.7中引入的。

  3. 除了将hive.auto.convert.join设置为true之外,你还可以将hive.optimize.skewjoin设置为true。这将解决1中描述的数据偏斜问题。


5
非常感谢您的回复,Mark。非常感激。
经过多个小时的努力,我最终发现了在连接语句中表的顺序对结果有影响。为了获得最佳性能和内存管理,最后一个连接应该是最大的表。
改变我的连接语句中表的顺序解决了这个问题。
请参见“将最大的表放在最后”http://hive.apache.org/docs/r0.9.0/language_manual/joins.html 您上面的解释也非常有用。非常感谢。

10
如果你同意Mark Grover的解决方案,你应该“接受”他的答案,而不是接受你自己的解决方案,因为后者并不是真正的解决方案,而只是对正确答案的赞赏。 - Mayank Jaiswal
1
对上面的评论点个赞。但我认为,由于他是 SO 的新手,可能还没有意识到这里的规则。 - Pratik Khadloya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接