Scala 如何通过.map将一个RDD传递给另一个RDD

Scala 如何通过.map将一个RDD传递给另一个RDD,scala,apache-spark,Scala,Apache Spark,我有两个rdd,我想为rdd1的每一项计算RDD2项。因此,我在一个用户定义的函数中传递RDD2,如下所示,但我得到的错误是,rdd1不能在另一个rdd中传递。如果我想在两个rdd上执行操作,我可以知道如何实现这一点吗 例如: RDD1.map(line=>函数(line,RDD2))正如错误所说,Spark不支持嵌套RDD。通常,您必须通过重新设计算法来解决这个问题 如何做到这一点取决于实际的用例,在函数中到底发生了什么,以及它的输出是什么 有时,使用一个RDD1.cartesian(RDD2

我有两个rdd,我想为rdd1的每一项计算RDD2项。因此,我在一个用户定义的函数中传递RDD2,如下所示,但我得到的错误是,
rdd1不能在另一个rdd中传递。如果我想在两个rdd上执行操作,我可以知道如何实现这一点吗

例如:


RDD1.map(line=>函数(line,RDD2))
正如错误所说,Spark不支持嵌套RDD。通常,您必须通过重新设计算法来解决这个问题

如何做到这一点取决于实际的用例,在
函数中到底发生了什么,以及它的输出是什么

有时,使用一个
RDD1.cartesian(RDD2)
,对每个元组执行操作,然后按键进行缩减,就可以了。有时,如果您有
(K,V)
键入两个RDD之间的连接将起作用

如果RDD2很小,您可以始终在驱动程序中收集它,将其设置为广播变量,并在
函数中使用该变量,而不是
RDD2

@编辑:

例如,让我们假设您的RDD包含字符串,并且
函数将计算
RDD
中的给定记录在
RDD2
中出现的次数:

def function(line: String, rdd: RDD[String]): (String, Int) = {
   (line, rdd.filter(_ == line).count)
} 
这将返回一个
RDD[(字符串,Int)]

Idea1

您可以尝试使用usingrdd的笛卡尔方法

val cartesianProduct = RDD1.cartesian(RDD2) // creates RDD[(String, String)]
                           .map( (r1,r2) => (r1, function2) ) // creates RDD[(String, Int)]
                           .reduceByKey( (c1,c2) => c1 + c2 ) // final RDD[(String, Int)]
这里
function2
接受
r1
r2
(它们是字符串)并返回
1
,如果它们相等,则返回
0
。最后的映射将产生一个
RDD
,它将具有元组,其中键将是
r1
中的记录,值将是总计数

问题1:但是,如果在
RDD1
中有重复的字符串,这将不起作用。你得考虑一下。如果
RDD1
记录有一些唯一的id,那就完美了

问题2:这确实会创建很多对(对于两个RDD中的1mln记录,它会创建大约500bln对),速度会很慢,并且很可能会导致很多错误

Idea2

我不理解您对RDD2大小
lacs
的评论,因此这可能有效,也可能无效:

val rdd2array = sc.broadcast(RDD2.collect())
val result = RDD1.map(line => function(line, rdd2array))
问题:这可能会破坏你的记忆<在
驱动程序上调用code>collect()
,并且
来自
rdd2
的所有记录都将加载到驱动程序节点上的内存中

Idea3


根据用例的不同,还有其他克服这种情况的方法,例如,与您的用例类似(双关语不是有意的)。这方面的一个替代解决方案是。

感谢您的回复。我在一个RDD中有类似的用例,我有数百万行和200多列,而在另一个RDD中,我有LAC记录和列。我需要从RDD1中提取每一行,并需要对整个RDD2进行一些比较和计算。为了实现这一点,我想在RDD1中传递这个RDD2。但是如果我们不能支持spark中的嵌套RDD,那么如何克服这个问题。@RaghavendraKulkarni用一个example@MateuszDymczyk,“lac”==100000(在印度使用).非常感谢MateuszDymczyk@RaghavendraKulkarni没问题。它解决了你的问题吗?如果是的话,如果你接受这个答案,那就太酷了。如果没有,我们可以考虑一些不同的东西,如果你提供更多的细节:-)