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