【问题标题】:Gzip: merge a set of small files (<64mb) into several larger files (64mb or 128mb)Gzip:将一组小文件(<64mb)合并成几个大文件(64mb 或 128mb)
【发布时间】:2013-06-20 14:52:27
【问题描述】:

我有大约 14000 个小 .gz 文件(从 90kb 到 4mb),它们都加载到 HDFS 中的同一目录中。

所以它们每个的大小都与 HDFS 的标准 64mb 或 128mb 块大小相距甚远,这在运行 MR 时可能会导致严重的麻烦(“小文件问题”,请参阅 cloudera 的 this 博客文章)处理这些文件的作业。

上述博客文章包含许多解决此问题的方法,主要涉及编写 MapReduce 作业或使用 Hadoop 存档 (HAR)。

不过,我想从源头解决问题,将小文件合并为 64mb 或 128mb 的 .gz 文件,然后直接输入 HDFS。

最简单的方法是什么?

【问题讨论】:

标签: bash hadoop gzip hdfs


【解决方案1】:
cat small-*.gz > large.gz

应该够了。假设您不需要从那里提取单独的文件,并且数据就足够了。

如果你想要单独的文件,只需 tar:

tar cf large.tar small-*.gz

【讨论】:

  • 如果我理解正确,您的两个答案都会生成一个大的 gzip 文件。但是,我更喜欢 Amar 链接的解决方案,但限制是文件尽可能接近但小于 64MB(或可选地尽可能接近但小于 128MB)
  • 您想如何从此类文件中提取数据?只是一般的数据,还是单独的文件?
  • 我只想访问数据本身。每个文件都包含“逐行”样式的信息。它们像这样被馈送到 HDFS,然后会自动解压缩它们。所以我不想自己解压缩数据,小文件的哪一行最终在哪个大文件中并不重要。
  • 在这种情况下,只需:cat small-*.gz | split -b 64M -a 10 large.gz.
  • 对不起,改成:... |split -b64M -a 10 - large.gz.
【解决方案2】:

经过进一步实验,以下两个步骤可以满足我的要求:

zcat small-*.gz | split -d -l2000000 -a 3 - large_

这适用于我的情况,因为一条线的长度几乎没有变化。 2000000 行几乎正好对应 300Mb 文件。 不幸的是,由于某种原因,gzip 不能像这样通过管道传输,所以我必须再做一步:

gzip *

这也会压缩生成的大文件。 Gzip 将这些文件中的每一个压缩了约 5 倍,产生 60mb 的文件,从而满足了我接收 .gz 文件

【讨论】:

    猜你喜欢
    • 2010-12-10
    • 2017-03-22
    • 2020-02-24
    • 1970-01-01
    • 2015-09-09
    • 2016-10-01
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多