1

情况:我有一个 Postgres 数据库,其中包含一个包含数百万行的表,我正在尝试查询所有这些行以获取 MapReduce 作业。

根据我对 DBInputFormat 所做的研究,Hadoop 可能会尝试再次对新的映射器使用相同的查询,并且由于这些查询需要相当长的时间,我想以我认为的两种方式之一来防止这种情况发生向上:

1) Limit the job to only run 1 mapper that queries the whole table and call it 
   good.

或者

2) Somehow incorporate an offset in the query so that if Hadoop does try to use
   a new mapper it won't grab the same stuff.

我觉得选项(1)似乎更有希望,但我不知道这样的配置是否可行。Option(2) 在理论上听起来不错,但我不知道如何跟踪正在制作的映射器,以及是否有可能检测到并重新配置。

感谢您的帮助,我正在寻找一种方法来提取所有数据库表数据并且不运行多个相同的查询,因为那会浪费时间。

4

1 回答 1

3

DBInputFormat 基本上已经完成了您的选项 2。它确实在其查询中使用 LIMIT 和 OFFSET 来划分工作。例如:

  • Mapper 1 执行:SELECT field1, field2 FROM mytable ORDER BY keyfield LIMIT 100
  • Mapper 2 执行:SELECT field1, field2 FROM mytable ORDER BY keyfield LIMIT 100 OFFSET 100
  • Mapper 3 执行:SELECT field1, field2 FROM mytable ORDER BY keyfield LIMIT 100 OFFSET 200

因此,如果您在关键字段上有适当的索引,您可能不应该介意正在运行多个查询。你确实得到一些可能的返工是投机执行。有时hadoop会安排多个相同的任务,并且只使用先完成的输出。如果您愿意,可以通过设置以下属性来关闭它:

mapred.map.tasks.speculative.execution=false

但是,如果您没有可以有效地执行这些 ORDER、LIMIT、OFFSET 查询的合理密钥,那么所有这些都将是不可能的。这就是您可以考虑使用选项 1 的地方。您绝对可以进行该配置。设置属性:

mapred.map.tasks=1

从技术上讲,InputFormat 获得了运行多少 Map 任务的“最终决定权”,但 DBInputFormat 始终尊重此属性。

您可以考虑使用的另一个选项是一个名为sqoop的实用程序,它是为在关系数据库和 hadoop 之间传输数据而构建的。然而,这将使其成为一个两步过程:首先将数据从 Postgres 复制到 HDFS,然后运行 ​​MapReduce 作业。

于 2013-10-30T21:50:05.227 回答