我有一个关于在 Hadoop 中为多个映射器配置 Map/Side 内部连接的问题。
假设我有两个非常大的数据集 A 和 B,我使用相同的分区和排序算法将它们分成更小的部分。对于 A,假设我有 a(1) 到 a(10),而对于 B,我有 b(1) 到 b(10)。确保 a(1) 和 b(1) 包含相同的 key ,a(2) 和 b(2) 具有相同的 key ,依此类推。我想设置 10 个映射器,特别是映射器(1)到映射器(10)。据我了解,Map/Side join 是 mapper 之前的预处理任务,因此,我想加入 a(1) 和 b(1) for mapper(1),加入 a(2) 和 b( 2) 用于映射器(2),依此类推。

看了一些引用资料,我还是不太清楚这十个mapper是怎么配置的。我知道使用 CompositeInputFormat 我将能够加入两个文件,但似乎只配置了一个映射器并成对加入了 20 个文件(在 10 个连续任务中)。如何在真正的 Map/Reduce(并行 10 个任务)中配置所有这十个映射器并同时加入十个对?据我了解,十个映射器需要十个 CompositeInputFormat 设置,因为要加入的文件全都不同。我坚信这是实用且可行的,但我无法弄清楚我应该使用哪些确切的命令。

任何提示和建议都受到高度欢迎和赞赏。



非常感谢大卫和托马斯的回复!

感谢您对 Map-side Join 的先决条件的强调。是的,我知道排序、API 等。阅读您的评论后,我认为我的实际问题是在 CompositeInputFormat 中连接两个文件的多个拆分的正确表达式是什么。例如,我将 dataA 和 dataB 分别排序和减少到 2 个文件中:

/A/dataA-r-00000

/A/dataA-r-00001

/B/dataB-r-00000

/B/dataB-r-00001

我现在使用的表达式命令是:

内部(tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,"/A/dataA-r-00000"),tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,"/B/dataB-r-00000"))

它可以工作,但正如您所提到的,它只启动两个映射器(因为内部连接防止拆分)并且如果文件很大,效率可能会非常低。如果我想使用更多的映射器(比如另外 2 个映射器来连接 dataA-r-00001 和 dataB-r-00001),我应该如何构造表达式,它是这样的:

String joinexpression = "inner(tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/A/dataA-r-00000'),tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/B/dataB-r- 00000'), tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/A/dataA-r-00001'),tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/B/dataB-r-00001' ))";

但我认为这可能是错误的,因为上面的命令实际上执行了四个文件的内部连接(在我的情况下这不会导致任何结果,因为文件 *r-00000 和 *r-00001 具有不重叠的键)。

或者我可以只使用两个目录作为输入,例如:

String joinexpression = "inner(tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/A/'),tbl(org.apache.hadoop.mapred.KeyValueTextInputFormat,'/B/'))";

内连接将根据文件结尾自动匹配对,比如“00000”到“00000”,“00001”到“00001”?我被困在这一点上,因为我需要构造表达式并将其传递给

conf.set("mapred.join.expr", joinexpression);

所以一句话,如果我想使用更多的映射器同时连接多对文件,我应该如何构建正确的表达式?

最佳答案

有 map- 和 reduce 侧连接。
您建议使用 map 侧连接,它在映射器内部而不是在它之前执行。
双方必须具有相同的键和值类型。因此,您不能加入 LongWritableText ,尽管它们可能具有相同的值。

还有一些微妙的注意事项:

  • 输入文件必须排序,所以它可能是一个 reducer 输出
  • 您可以通过设置作业中应该对数据集进行排序的 reducer 的数量来控制 join-map-phase 中映射器的数量

  • 整个过程基本上是这样工作的:你有数据集 A 和数据集 B,它们共享相同的 key ,比如 LongWritable
  • 运行两个作业,通过它们的键对两个数据集进行排序,两个作业都必须将 reducer 的数量设置为相同的数量,比如 2。
  • 这将为每个数据集
  • 生成 2 个 排序的 文件
  • 现在您设置了连接数据集的作业,此作业将生成 2 个映射器。如果您在之前的工作中将减少数字设置得更高,则可能会更多。
  • 在 reduce 步骤中做任何你喜欢的事情。

  • 如果要加入的文件数量不相等,则会导致作业设置过程中出现异常。

    设置连接有点痛苦,主要是因为如果你的版本低于 0.21.x,你必须使用旧的 API 来映射器和化器。

    This document describes very well how it works. 一直滚动到底部,遗憾的是在最新的 Hadoop 文档中不知何故缺少此文档。

    另一个很好的引用是“Hadoop the Definitive Guide”,它更详细地解释了所有这些并附有示例。

    关于hadoop - 在 Hadoop Map/Reduce 中为多个映射器配置 Map Side join,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6323544/

    10-16 03:09