在 Hadoop 中更改文件拆分大小
Posted
技术标签:
【中文标题】在 Hadoop 中更改文件拆分大小【英文标题】:Change File Split size in Hadoop 【发布时间】:2012-03-29 12:12:06 【问题描述】:我在 HDFS 目录中有一堆小文件。虽然文件的体积相对较小,但每个文件的处理时间量很大。也就是说,64mb
文件(TextInputFormat
的默认拆分大小)甚至需要几个小时才能处理。
我需要做的是减小分割大小,这样我就可以利用更多节点来完成一项工作。
所以问题是,如何通过10kb
分割文件?我是否需要为此实现自己的InputFormat
和RecordReader
,或者是否需要设置任何参数?谢谢。
【问题讨论】:
【参考方案1】:mapred.max.split.size
参数可以为每个作业单独设置,这正是您所寻找的。不要更改 dfs.block.size
,因为这对于 HDFS 来说是全局性的,可能会导致问题。
【讨论】:
dfs.block.size 不一定是全局的;您可以将特定文件设置为与文件系统的默认值不同的块大小。不过,我同意 mapred.max.split.size 在这种情况下可能是要走的路。mapred.max.split.size
is deprecated. The new property name is mapreduce.input.fileinputformat.split.maxsize
。我还发现this answer 对调整输入拆分大小很有帮助。【参考方案2】:
Hadoop权威指南,第203页“最大拆分大小默认为Java long类型可以表示的最大值。只有小于块大小时才有效,强制拆分为小于一个块。 分割大小由以下公式计算:
max(minimumSize, min(maximumSize, blockSize))
默认
minimumSize < blockSize < maximumSize
所以分割大小是blockSize
例如,
Minimum Split Size 1
Maximum Split Size 32mb
Block Size 64mb
Split Size 32mb
Hadoop 处理少量大文件比处理大量小文件效果更好。这样做的一个原因是 FileInputFormat 以这样一种方式生成拆分,即每个拆分都是单个文件的全部或一部分。如果文件非常小(“小”意味着比 HDFS 块小得多)并且数量很多,那么每个 map 任务将处理非常少的输入,并且会有很多输入(每个文件一个),每一项都会增加额外的簿记开销。比较一个分成 16 个 64mb 块的 1gb 文件和 10.000 个左右 100kb 的文件。 10.000 个文件每个使用一个映射,工作时间可能比具有单个输入文件和 16 个映射任务的等效文件慢数十或数百倍。
【讨论】:
【参考方案3】:编写一个扩展 combinefileinputformat 的自定义输入格式[在 hadoop 发行版中具有自己的优点和缺点基础]。它将输入拆分组合成 mapred.max.split.size 中指定的值
【讨论】:
【参考方案4】:这是一个片段,它说明了在没有神奇配置字符串的情况下执行此处所需操作的正确方法。需要的常量在FileInputFormat
中定义。如果需要,可以从默认的 HDFS 块常量中获取块大小,但它很有可能是用户定义的。
这里我只是将最大拆分大小除以 2(如果已定义)。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
// ....
final long DEFAULT_SPLIT_SIZE = 128 * 1024 * 1024;
final Configuration conf = ...
// We need to lower input block size by factor of two.
conf.setLong(
FileInputFormat.SPLIT_MAXSIZE,
conf.getLong(
FileInputFormat.SPLIT_MAXSIZE, DEFAULT_SPLIT_SIZE) / 2);
【讨论】:
以上是关于在 Hadoop 中更改文件拆分大小的主要内容,如果未能解决你的问题,请参考以下文章