在部分HDFS文件上运行MR作业

时间:2012-01-26 03:49:02

标签: hadoop

想象一下,你有一个存储在hdtf中的大文件,其中包含结构化数据。现在的目标是只处理文件中的一部分数据,就像文件中第二列值介于两者之间的所有行一样。是否可以启动MR作业,以便hdfs仅传输文件的相关部分,而不是将所有内容流式传输到映射器。

原因是我想通过只处理我需要的部分来加快工作速度。可能一种方法是运行MR作业来创建一个新文件,但我想知道是否可以避免这种情况?

请注意,目标是将数据保存在HDFS中,我不想从数据库中读取和写入。

4 个答案:

答案 0 :(得分:2)

HDFS将文件作为一堆字节存储在块中,并且没有索引,因此无法只读取文件的一部分(至少在撰写本文时)。此外,任何给定的映射器都可能获得文件的第一个块或第400个,并且您无法控制它。

也就是说,MapReduce的重点是在多台机器上分配负载。在我们的集群中,我们一次最多运行28个映射器(4个节点上每个节点7个),因此如果我的输入文件是1TB,则每个映射插槽最终可能只读取总文件的3%,或大约30GB。您只需在映射器中执行所需的过滤器,并仅处理您感兴趣的行。

如果您确实需要过滤访问权限,可能需要查看将数据存储在HBase中。它可以充当MapReduce作业的本地源,提供过滤的读取,并将其数据存储在HDFS上,因此您仍处于分布式世界中。

答案 1 :(得分:1)

一个答案是看蜂巢解决这个问题的方式。数据位于“表”中,实际上只是关于磁盘上文件的元数据。 Hive允许您设置分区表的列。这会为每个分区创建一个单独的文件夹,因此如果您按日期对文件进行分区,则可以:

/mytable/2011-12-01
/mytable/2011-12-02

日期目录中的内容是实际文件。因此,如果您随后运行了如下查询:

SELECT * FROM mytable WHERE dt ='2011-12-01'

只有/ mytable / 2011-12-01中的文件才会被输入作业。

首先,如果您想要这样的功能,您要么想要升级到更高级别的语言(hive / pig),要么需要推出自己的解决方案。

答案 2 :(得分:0)

处理成本的很大一部分 - 是数据解析,以便为Mapper生成键值。我们在那里创建(通常)每个值一个java对象+一些容器。在CPU和垃圾收集器压力方面都很昂贵 我建议解决方案“在中间”。您可以编写输入格式,该格式将读取输入流并在早期阶段跳过不相关的数据(例如,通过查看字符串的几个第一个字节)。
因此,您将读取所有数据,但实际上是解析并传递给Mapper的唯一部分 我会考虑的另一种方法是使用RCFile格式(或其他列式格式),并注意相关和非相关数据将位于不同的列中。

答案 3 :(得分:0)

如果要处理的文件具有关于其文件名的某些唯一属性(如扩展名或部分文件名匹配),则还可以使用FileInputFormat的setInputPathFilter方法忽略除MR作业所需的所有文件。 Hadoop默认忽略所有“.xxx”和_xxx“文件/目录,但您可以使用setInputPathFilter进行扩展。

正如其他人已经指出的那样,你可能会从你的群集中获得次优的性能,从而打破了“每个映射器一个块”范例,但有时这是可以接受的。有时可以采取更多“正确行事”,特别是如果你正在处理少量数据&重新构建和/或重新转储到HBase的时间将超过以次优的方式运行工作所需的额外时间。