调整Hive查询的性能

use*_*355 11 memory performance hive exception

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

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

奇怪的是,如果我删除join子句并只选择表中的数据(稍高的音量),那么查询工作正常.

我对Hive很新.我无法理解为什么这个连接导致内存异常.

关于如何编写Hive查询以便它们不会导致这些问题,我是否应该注意一些事项?任何人都可以解释为什么连接可能会导致此问题,但选择更大的数据量和相同数量的列不会.

感谢你对此的看法.谢谢

小智 36

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

为了更好地理解这个问题,让我们来看看Hive中"常规"内连接的工作原理.

Hive加入MapReduce:

以下是如何将Hive中的内部联接编译为MapReduce的简化说明.通常,如果您有两个表t1和t2,并且连接查询如下:

SELECT
   t1.key, t1.value, t2.value
FROM
   t1
   JOIN
   t2 (ON t1.key = t2.key);
Run Code Online (Sandbox Code Playgroud)

其中,t1具有以下内容:

k_1    v1_1
k_2    v1_2
k_3    v1_3    
Run Code Online (Sandbox Code Playgroud)

其中,t2具有以下内容:

k_2    v2_2
k_3    v2_3
k_4    v2_4    
Run Code Online (Sandbox Code Playgroud)

我们希望连接结果是

k_2    v1_2    v2_2
k_3    v1_3    v2_3
Run Code Online (Sandbox Code Playgroud)

假设表存储在HDFS上,它们的内容将被拆分为File Splits.映射器将文件拆分为输入,并将密钥作为表的键列发出,值作为表的值列和标志的复合(表示记录来自哪个表,即t1或t2) .

对于t1:

k_1, <v1_1, t1>
k_2, <v1_2, t1>
k_3, <v1_3, t1>
Run Code Online (Sandbox Code Playgroud)

对于t2:

k_2, <v2_2, t2>
k_3, <v2_3, t2>
k_4, <v2_4, t2>
Run Code Online (Sandbox Code Playgroud)

现在,这些发出的记录经过洗牌阶段,其中具有相同键的所有记录被组合在一起并被发送到减速器.每个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>>
Run Code Online (Sandbox Code Playgroud)

以下是减速机中发生的情况.对于值列表中的每个值,如果值对应于不同的表,则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.您可以通过set mapred.child.java.opts;在Hive shell中执行来查询此参数的当前值.

  2. 您可以尝试使用"常规"连接的替代方法,例如地图连接.上面的连接说明适用于常规连接,其中连接发生在reducers中.根据您使用的Hive的版本,Hive可以自动将常规连接转换为更快的地图连接(因为连接发生在地图阶段).要启用优化,请设置hive.auto.convert.jointrue.该属性是在Hive 0.7中引入的

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


use*_*355 6

非常感谢Mark的回应.非常感激.

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

在join语句中更改表的顺序解决了问题.

请参阅最新的表格http://hive.apache.org/docs/r0.9.0/language_manual/joins.html

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

  • 嘿,如果你同意他的解决方案,你应该"接受"Mark Grover的答案,而不是接受你自己的解决方案,这不是一个真正的解决方案,而是对正确答案的欣赏. (7认同)