由于某种原因,这个脚本在一个小输入上产生了60,000个地图作业:
A1 = LOAD '$directory1' USING CustomLoader AS key:chararray;
A = FOREACH A1 GENERATE CustomParser(key) AS key:chararray;
B = LOAD '$filename1' USING PigStorage AS (key:chararray);
result = JOIN A BY key, B BY key USING 'replicated';
directory1有几个文件组成大约10000行数据,而filename1也有~10000行数据,所有这些都是短字符串。目录和文件都存储在HDFS中。在10s-100s千字节的范围内,两者都不是特别大。但是,当我在hadoop中运行脚本时,它会生成60,000个映射作业。这导致了许多其他问题 - 有时应用程序管理器耗尽内存,有时它会在随机播放阶段挂起,以及其他各种类型的内存不足错误。
似乎不应该为这么小的输入创建这么多的分割。我已经尝试增加max.CombinedSplitSize,mapred.min.split.size和dfs.block.size,但没有任何影响地图的数量(这是有意义的,因为它是我正在使用的少量小文件) 。我可能会继续增加工作中投入的资源,但在某种程度上这些价值是我无法控制的。
值得注意的是,这个脚本在本地工作正常 - 只有在实际的hadoop集群上运行并实际从HDFS读取此问题才会发生。
是否还有其他人遇到类似问题,如果有,您更改了什么来解决问题?
答案 0 :(得分:0)
原来问题出在我的CustomLoader中(我不会预料到的)。加载器可以定义自己的分割,并创建了大量的分割,转换为大量的地图。这个自定义加载器显然没有将拆分组合在一起(尽管我认为它们可能不会默认组合),因此即使许多拆分为空或小,它们每个都会产生自己的地图作业。由于在我的所有配置更改后加载了自定义加载程序,因此它会覆盖可让我对组进行分组的配置。
对于那些感兴趣的人,我在子类化的InputFormat类的List<InputSplit> getSplits(final JobContext context)
方法中找到了分裂问题,该方法是从LoadFunc的自定义子类中的InputFormat getInputFormat()
返回的。