使用Hadoop通过两个数据集进行映射

使用Hadoop通过两个数据集进行映射,hadoop,mapreduce,Hadoop,Mapreduce,假设我有两个键值数据集——数据集A和B,让我们调用它们。我想用集合B中的数据更新集合A中的所有数据,其中两个键匹配 因为我要处理如此大量的数据,所以我使用Hadoop来MapReduce。我关心的是要在A和B之间进行键匹配,我需要将所有集合A(大量数据)加载到每个映射器实例的内存中。这似乎效率很低 是否有一种推荐的方法可以做到这一点,而不需要每次都重复加载工作 一些伪代码来澄清我目前正在做的事情: Load in Data Set A # This seems like the expensiv

假设我有两个键值数据集——数据集A和B,让我们调用它们。我想用集合B中的数据更新集合A中的所有数据,其中两个键匹配

因为我要处理如此大量的数据,所以我使用Hadoop来MapReduce。我关心的是要在A和B之间进行键匹配,我需要将所有集合A(大量数据)加载到每个映射器实例的内存中。这似乎效率很低

是否有一种推荐的方法可以做到这一点,而不需要每次都重复加载工作

一些伪代码来澄清我目前正在做的事情:

Load in Data Set A # This seems like the expensive step to always be doing
Foreach key/value in Data Set B:
   If key is in Data Set A:
      Update Data Seta A

根据文档,MapReduce框架包括:

  • 地图
  • 排序/分区
  • 联合收割机(可选)
  • 减少
  • 您已经描述了执行联接的一种方法:将所有集合A加载到每个映射器的内存中。你是对的,这是低效的

    相反,请注意,如果按键对两个集合进行排序和分区,则可以将一个大联接划分为任意多个小联接。MapReduce按上面步骤(2)中的键对每个映射器的输出进行排序。然后按键对排序后的映射输出进行分区,这样每个减速机就创建一个分区。对于每个唯一键,减速器将接收集合A和集合B中的所有值

    要完成连接,Reducer只需输出键和集合B中的更新值(如果存在);否则,输出集合A中的键和原始值。要区分集合A和集合B中的值,请尝试在映射器的输出值上设置标志。

    by Cloudera从12分钟左右开始,详细介绍了如何通过MapReduce进行大规模连接。
    以下是他用伪代码将文件B中的记录连接到密钥K中文件A中的记录的基本步骤。如果这里有什么不清楚的地方,我建议看视频,因为他比我解释得好得多

    在映射器中:

    K from file A:
      tag K to identify as Primary Key
      emit <K, value of K>
    
    K from file B:
      tag K to identify as Foreign Key
      emit <K, record>
    
    文件A中的
    K:
    标记K以标识为主键
    发出
    文件B中的K:
    标记K以标识为外键
    发出
    
    编写一个将忽略PK/FK标记的分类程序和分组程序,以便将您的记录发送到同一个缩减器,而不管它们是PK记录还是FK记录,并分组在一起

    编写一个比较器,比较PK和FK键,并首先发送PK

    此步骤的结果是,具有相同键的所有记录将发送到同一个Reducer,并位于要缩减的同一组值中。首先是标记有PK的记录,然后是B中需要加入的所有记录。现在,减速器:

    value_of_PK = values[0] // First value is the value of your primary key
    for value in values[1:]:
      value.replace(FK,value_of_PK) // Replace the foreign key with the key's value
      emit <key, value>
    
    value\u of_PK=values[0]//第一个值是主键的值
    对于值中的值[1:]:
    value.replace(FK,value\u of_PK)//用键的值替换外键
    发出
    

    其结果将是文件B,文件A中所有出现的K都替换为K的值。您还可以扩展它以实现完整的内部联接,或将两个文件全部写入直接数据库存储,但这些都是非常琐碎的修改,一旦你得到了这个工作。

    到目前为止所有的答案都是正确的-这应该是一个Reduce-side连接。。。但是没有必要重新发明轮子!你有没有考虑过,或者为此?它们都有内置的连接,并且进行了相当好的优化。

    如果我理解正确,您是说Hadoop
    -input
    应该是-both-集合A和B(带有一个标志以在值中区分它们),然后在缩减步骤中将它们分组在一起,这样就可以连接它们。对吗?对,你应该把A和B都输入到你的映射器中,并确保你输出了一个标志,这样还原器就可以区分这两个。我还假设您正在编写自己的
    Map
    (实现
    mapred.Mapper
    )和
    Reduce
    (实现
    mapred.Reducer
    )类。正如@joe-k在一个单独的回答中所说,Pig、Hive和Cascading都是合法的解决方案,可以为您生成此代码并在Hadoop上运行。您可以使用Bloom Filter进行小型优化,如果集合a比集合B大得多,并且存在与集合B不匹配的记录,并且集合B不适合内存,这将非常有效。创建一个MapReduce作业,该作业在集合B上训练Bloom筛选器,而不是在最终MapReduce作业中执行所有建议的操作,但是在使用Bloom筛选器的Mapper筛选器集合a中,这将减少集合a中没有匹配集合B记录的溢出记录量,因此您的作业可能会运行得更快。很好。标记A和B中的散列值而不是键本身,难道不起作用吗?然后我就不需要编写自己的分类器和Grouper,我可以在Reduce步骤中循环整个组,看看它们是否都是there@babonk对不起,我不知道你的意思。你的意思是在散列阶段标记值?你似乎建议标记K,而不是K的值。我只是说标记值可能更容易,所以我不需要编写自己的分类器/grouper@babonk你可以这样做,但是你没有办法确保PK是第一位的,这意味着您必须在值列表中循环两次。排序PK首先将时间复杂度从O(2n)降低到O(n),如果你有一个小数据集,这没什么大不了的,但是当你以TB为单位工作时,它会产生巨大的变化。哇,很酷。现在,我将坚持使用Hadoop,但我可能会在以后学习其中一种框架