>情况:我有一个Postgres DB,其中包含一个包含数百万行的表,我正在尝试查询所有这些行以获取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) 似乎更有希望,但我不知道这样的配置是否可行。选项(2)在理论上听起来不错,但我不知道如何跟踪正在制作的映射器,以及是否有可能检测到并重新配置。
感谢帮助,我正在寻找一种方法来提取所有数据库表数据,而不是运行几个相同的查询,因为那会浪费时间。
DBInputFormat基本上已经完成了你的选项2。它确实在其查询中使用 LIMIT 和 OFFSET 来划分工作。例如:
- 映射器 1 执行:从 mytable 中选择字段 1、字段 2 按键字段排序限制 100
- 映射器 2 执行:从 mytable 中选择字段 1、字段 2 按键字段排序 限制 100 偏移量 100
- 映射器 3 执行:从我的表中选择字段 1、字段 2 按键字段排序 限制 100 偏移量 200
因此,如果您在键字段上有适当的索引,您可能不应该介意正在运行多个查询。你得到一些可能的返工的地方是推测性执行。有时 hadoop 会安排同一任务的倍数,并且只使用先完成的输出。如果需要,可以通过设置以下属性来关闭此功能:
mapred.map.tasks.speculative.execution=false
但是,如果您没有可以有效地执行这些 ORDER、LIMIT、OFFSET 查询的合理键,那么所有这些都不在窗口。这就是您可以考虑使用选项 1 的地方。您绝对可以执行该配置。设置属性:
mapred.map.tasks=1
从技术上讲,InputFormat 对运行多少 Map 任务拥有"最终决定权",但 DBInputFormat 始终尊重此属性。
您可以考虑使用的另一个选项是一个名为 sqoop 的实用程序,它用于在关系数据库和 hadoop 之间传输数据。然而,这将成为一个两步过程:首先将数据从Postgres复制到HDFS,然后运行MapReduce作业。