假设我有两个相当大的数据集 - 第一个称为“Base”,它包含2亿个制表符分隔的行,第二个是调用“MatchSet”,它有1000万个制表符分隔的相似数据行。
假设我还有一个名为Match(row1,row2)的任意函数,而Match()基本上包含一些启发式方法,用于查看row1(来自MatchSet)并将其与row2(来自Base)进行比较并确定它们是否相似某种程度上来说。
假设在Match()中实现的规则是自定义和复杂的规则,也就是说不是简单的字符串匹配,涉及一些专有方法。让我们说现在Match(row1,row2)是用伪代码编写的,所以用另一种语言实现不是问题(虽然它今天在C ++中)。
在一个线性模型中,也就是在一个巨型处理器上运行的程序 - 我们将从MatchSet读取每一行,从Base读取每一行,并使用Match()比较一个并写出我们的匹配统计数据。例如,我们可能会捕获:来自MatchSet的X记录是强匹配,来自MatchSet的Y记录是弱匹配,来自MatchSet的Z记录不匹配。我们还会将强/弱/非值写入单独的文件以供检查。 Aka,一个嵌套的循环:
for each row1 in MatchSet
{
for each row2 in Base
{
var type = Match(row1,row2);
switch(type)
{
//do something based on type
}
}
}
我开始考虑将Hadoop流式传输作为一种在短时间内将这些比较作为批处理作业运行的方法。但是,对于这类问题,我有点难以理解地图 - 减少范例。
我在这一点上非常清楚如何从hadoop获取单个输入,使用映射函数处理数据然后发出结果以减少。然而,比较两组记录的“嵌套循环”方法让我感到不安。
我最接近解决方案的是,我基本上仍然需要在2亿条记录中并行进行1000万条记录比较,以便每个节点有2亿个节点* 1000万次迭代。这是最有效的方法吗?
答案 0 :(得分:2)
根据您的描述,在我看来,您的问题可能是任意复杂的,可能是curse of dimensionality的受害者。
想象一下,例如,您的行代表n维向量,并且您的匹配函数基于Base向量和MatchSet向量之间的欧几里德距离是“强”,“弱”或“不匹配”。通过在速度,记忆和近似答案的质量之间进行权衡,有很多很好的技术可以解决这些问题。重要的是,这些技术通常具有已知的时间和空间界限,以及在给定MatchSet原型周围的某个距离内找到一个点的概率,所有这些都取决于算法的某些参数。
请考虑阅读以下内容,而不是让我在这里絮絮叨叨:
现在,另一方面,如果您可以设计一个直接适用于某种形式的散列的方案,那么您可以使用这样的散列(甚至少量可能的散列键,轻松地为每个记录生成一个键,其中一个匹配查询“基础”数据),问题变成一个简单的大( - )规模连接。 (我说“较大”,因为如果问题确实是连接,加入200M行和10M行是相当小的)。例如,考虑CDDB计算任何音乐CD CDDB1 calculation的32位ID的方式。有时,给定标题可能产生略微不同的ID(即相同标题的不同CD,或甚至相同的CD读取数次)。但总的来说,该标题有一小组不同的ID。以MatchSet的小型复制为代价,在这种情况下,您可以获得非常快速的搜索结果。
答案 1 :(得分:0)
检查论文“Data-Intensive Text Processing
with MapReduce”中的Section 3.5 - Relational Joins
。我没有详细介绍,但它可能对你有帮助。
答案 2 :(得分:0)
这是一个老问题,但您提出的解决方案是正确的,假设您的单个流作业执行200M * 10M Match()计算。通过N批次(200M / N)* 10M计算,您已经实现了N加速因子。通过在映射阶段进行计算,然后将结果阈值处理并将结果导向强/弱/无匹配减少器,您可以将结果收集到单独的文件中。
如果可以使用其他优化,他们会同时适用于单流和并行版本。示例包括阻塞,因此您需要执行少于200M * 10M的计算或预先计算10M匹配集的算法常量部分。