13

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

由于超出 Java GC 开销限制,查询失败。

奇怪的是,如果我删除连接子句并从表中选择数据(略高一些),那么查询就可以正常工作。

我对 Hive 很陌生。我不明白为什么这个连接会导致内存异常。

关于如何编写 Hive 查询,我应该注意些什么,以免它们引起这些问题?谁能解释为什么联接可能会导致此问题,但选择更多数据和相同数量的列却不会。

感谢您对此的想法。谢谢

4

2 回答 2

41

根据 Hive 的版本和您的配置,您的问题的答案可能会有所不同。如果您可以共享您的确切查询以及两个表的创建语句以及它们的大小估计,那将会更容易。

为了更好地理解这个问题,让我们看看 Hive 中的“常规”内部连接是如何工作的。

在 MapReduce 中加入 Hive:

这是 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>

对于 t2:

k_2, <v2_2, t2>
k_3, <v2_3, t2>
k_4, <v2_4, t2>

现在,这些发出的记录经过混洗阶段,其中所有具有相同键的记录被组合在一起并发送到减速器。每个 reduce 操作的上下文是一个键和一个包含与该键对应的所有值的列表。在实践中,一个 reducer 将执行多个 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获取数据时,某个key对应的value列表很长,导致出错。为了缓解这个问题,您可以尝试增加 JVM 可用的内存。您可以通过设置为hive-site.xml 中mapred.child.java.opts的值来执行此操作。您可以通过在 Hive shell 中-Xmx512M执行来查询此参数的当前值。set mapred.child.java.opts;

  2. 您可以尝试使用“常规”连接的替代方法,例如地图连接。以上对连接的解释适用于连接发生在减速器中的常规连接。根据您使用的 Hive 版本,Hive 可能会自动将常规连接转换为更快的映射连接(因为连接发生在映射阶段)。要启用优化,请设置hive.auto.convert.jointrue。此属性是在Hive 0.7中引入的

  3. 除了设置hive.auto.convert.jointrue,您还可以设置hive.optimize.skewjointrue。这将解决 1 中描述的数据问题中的偏差。

于 2012-07-10T02:32:42.063 回答
5

非常感谢马克的回复。非常感激。

几个小时后,我最终发现 join 语句中表的顺序有所不同。为了获得最佳性能和内存管理,最后一个连接应该是最大的表。

在 join 语句中更改我的表的顺序解决了这个问题。

请参阅http://hive.apache.org/docs/r0.9.0/language_manual/joins.html上的最大表最后

您上面的解释也非常有用。非常感谢

于 2012-07-10T03:40:19.670 回答