【问题标题】:Merging multiple files into one within Hadoop在 Hadoop 中将多个文件合并为一个
【发布时间】:2011-04-02 16:08:49
【问题描述】:

我将多个小文件放入我的输入目录中,我想在不使用本地文件系统或编写 mapreds 的情况下将它们合并到一个文件中。有没有办法我可以使用 hadoof fs 命令或 Pig 来做到这一点?

谢谢!

【问题讨论】:

  • 如果您的问题已得到解答,您应该接受答案。

标签: hadoop apache-pig


【解决方案1】:

为了将所有内容保持在网格上,请使用带有单个 reducer 的 hadoop 流,并将 cat 作为映射器和 reducer(基本上是一个 noop) - 使用 MR 标志添加压缩。

hadoop jar \
    $HADOOP_PREFIX/share/hadoop/tools/lib/hadoop-streaming.jar \<br>
    -Dmapred.reduce.tasks=1 \
    -Dmapred.job.queue.name=$QUEUE \
    -input "$INPUT" \
    -output "$OUTPUT" \
    -mapper cat \
    -reducer cat

如果你想压缩添加
-Dmapred.output.compress=真\ -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec

【讨论】:

  • 我认为这是最好的方法。
  • 我想这会改变行的顺序?
  • @AndredeMiranda 我认为顺序将是确定的,按键排序,因为我们只有一个减速器。这是基于回顾 shuffle、sort、reducer 模型。
  • 这不是最好的答案;这就是答案。所有其他答案都不正确(例如 fs -getmerge 会将文件放在本地,而不是放在 hdfs 上)
  • 呃,这样做会在每一行的末尾添加一个表格......我们应该如何解决这个问题?
【解决方案2】:
hadoop fs -getmerge <dir_of_input_files> <mergedsinglefile>

【讨论】:

  • 奇怪的是这没有给我任何结果。不知道为什么。
  • 可能你的目录只有空文件
  • 我认为mergedsinglefile 是本地的,不是分布式的
  • 这将导致本地文件系统上的文件,这是 OP 希望避免的
  • 这不会将文件放入 hdfs,而是将其保存到 dfs。然后我们需要使用 hdfs -put 将文件放回 hdfs。
【解决方案3】:

好的...我想出了一个使用hadoop fs 命令的方法 -

hadoop fs -cat [dir]/* | hadoop fs -put - [destination file]

当我测试它时它起作用了……有什么可以想到的陷阱吗?

谢谢!

【讨论】:

  • 但在这种情况下,您要将所有数据从 HDFS 下载到您正在运行命令的节点(本地节点?),然后将其上传到 HDFS。如果您有大量数据,这不是太有效
  • 另一个陷阱是有时您可能还会从标准输入中获得一些不需要的输入。当一些警告消息被困在输出中时,我曾经在启用 HA 的集群中遇到过它。
【解决方案4】:

如果您设置 fuse 以将 HDFS 挂载到本地目录,那么您的输出可以是挂载的文件系统。

例如,我在本地将我们的 HDFS 挂载到 /mnt/hdfs。我运行以下命令,效果很好:

hadoop fs -getmerge /reports/some_output /mnt/hdfs/reports/some_output.txt

当然,使用 fuse 将 HDFS 挂载到本地目录还有其他原因,但这对我们来说是一个很好的副作用。

【讨论】:

    【解决方案5】:

    您可以使用 HDFS 0.21 中的新工具 HDFSConcat 来执行此操作,而不会产生复制成本。

    【讨论】:

    • 感谢 Jeff,将研究 HDFSConcat。目前我们在 0.20.2,所以我现在正在创建一个所有文件的 Har,然后从 pig 中读取。这样数据就保留在 HDFS 中。
    • 我应该注意到,这个工具在issues.apache.org/jira/browse/HDFS-950 上突出显示了一些限制。文件必须具有相同的块大小并归同一用户所有。
    【解决方案6】:

    如果您在 Hortonworks 集群中工作并希望将 HDFS 位置中的多个文件合并到一个文件中,那么您可以运行运行单个减速器的“hadoop-streaming-2.7.1.2.3.2.0-2950.jar”jar并将合并后的文件放入 HDFS 输出位置。

    $ hadoop jar /usr/hdp/2.3.2.0-2950/hadoop-mapreduce/hadoop-streaming-2.7.1.2.3.2.0-2950.jar \

    -Dmapred.reduce.tasks=1 \
    -input "/hdfs/input/dir" \
    -output "/hdfs/output/dir" \
    -mapper cat \
    -reducer cat
    

    您可以从以下位置下载此 jar Get hadoop streaming jar

    如果您正在编写 spark 作业并希望获得一个合并文件以避免创建多个 RDD 和性能瓶颈,请在转换您的 RDD 之前使用这段代码

    sc.textFile("hdfs://...../part*).coalesce(1).saveAsTextFile("hdfs://...../filename)

    这会将所有部分文件合并为一个并再次保存到 hdfs 位置

    【讨论】:

      【解决方案7】:

      从 Apache Pig 的角度解决这个问题,

      通过 Pig 合并两个具有相同架构的文件,可以使用 UNION 命令

       A = load 'tmp/file1' Using PigStorage('\t') as ....(schema1)
       B = load 'tmp/file2' Using PigStorage('\t') as ....(schema1) 
       C = UNION A,B
       store C into 'tmp/fileoutput' Using PigStorage('\t')
      

      【讨论】:

        【解决方案8】:

        所有的解决方案都相当于做了一个

        hadoop fs -cat [dir]/* > tmp_local_file  
        hadoop fs -copyFromLocal tmp_local_file 
        

        仅表示本地 m/c I/O 处于数据传输的关键路径上。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-10-15
          • 1970-01-01
          • 2013-04-13
          • 2012-10-19
          • 2015-01-12
          • 1970-01-01
          相关资源
          最近更新 更多