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没有值,也没有发出任何值.因此,您可以获得内部联接所期望的结果.
好的,我该怎么办?
您的数据可能存在偏差.换句话说,当reducer获取数据时,对应于某个键的值列表非常长,这会导致错误.要解决此问题,您可以尝试增加JVM可用的内存.您可以通过设置hive-site.xml中mapred.child.java.opts的值来实现-Xmx512M.您可以通过set mapred.child.java.opts;在Hive shell中执行来查询此参数的当前值.
您可以尝试使用"常规"连接的替代方法,例如地图连接.上面的连接说明适用于常规连接,其中连接发生在reducers中.根据您使用的Hive的版本,Hive可以自动将常规连接转换为更快的地图连接(因为连接发生在地图阶段).要启用优化,请设置hive.auto.convert.join为true.该属性是在Hive 0.7中引入的
除了设置hive.auto.convert.join到true,您也可以设置hive.optimize.skewjoin到true.这将解决1中描述的数据问题的偏差.
非常感谢Mark的回应.非常感激.
几个小时后,我终于发现join语句中表的顺序有所不同.为了获得最佳性能和内存管理,最后一个连接应该是最大的表.
在join语句中更改表的顺序解决了问题.
请参阅最新的表格http://hive.apache.org/docs/r0.9.0/language_manual/joins.html
您上面的解释也非常有用.非常感谢