Scala 是否可以连接两个RDD';避免昂贵洗牌的价值观?

Scala 是否可以连接两个RDD';避免昂贵洗牌的价值观?,scala,join,apache-spark,Scala,Join,Apache Spark,我有两个RDD,它们都有两列(K,V)。在这些RDD的源中,键一个接一个地出现,对于每一行,为键分配一个不同的值。本文底部给出了创建RDD的文本文件 这两个RDD中的键是完全不同的,我想根据它们的值将两个RDD连接起来,并尝试找出每对的公共值。e、 g.我试图得出一个结果,例如(1-5,10),这意味着RDD1的键值“1”和RDD2的键值“5”共享10个共同值 我在一台有256 GB ram和72个内核的机器上工作。一个文本文件为500 MB,另一个为3 MB 这是我的密码: val conf

我有两个RDD,它们都有两列(K,V)。在这些RDD的源中,键一个接一个地出现,对于每一行,为键分配一个不同的值。本文底部给出了创建RDD的文本文件

这两个RDD中的键是完全不同的,我想根据它们的值将两个RDD连接起来,并尝试找出每对的公共值。e、 g.我试图得出一个结果,例如(1-5,10),这意味着RDD1的键值“1”和RDD2的键值“5”共享10个共同值

我在一台有256 GB ram和72个内核的机器上工作。一个文本文件为500 MB,另一个为3 MB

这是我的密码:

val conf = new SparkConf().setAppName("app").setMaster("local[*]").set("spark.shuffle.spill", "true")
.set("spark.shuffle.memoryFraction", "0.4")
.set("spark.executor.memory","128g")
.set("spark.driver.maxResultSize", "0")

val RDD1 = sc.textFile("\\t1.txt",1000).map{line => val s = line.split("\t"); (s(0),s(1))}

val RDD2 = sc.textFile("\\t2.txt",1000).map{line => val s = line.split("\t"); (s(1),s(0))}


val emp_newBC = sc.broadcast(emp_new.groupByKey.collectAsMap)

        val joined = emp.mapPartitions(iter => for {
          (k, v1) <- iter
          v2 <- emp_newBC.value.getOrElse(v1, Iterable())
        } yield (s"$k-$v2", 1))

    joined.foreach(println)

val result = joined.reduceByKey((a,b) => a+b)
join(RDD2).map(line=>(line._2,1)).reduceByKey((a,b)=>(a+b))

伪数据样本:

KEY VALUE
1   13894
1   17376
1   15688
1   22434
1   2282
1   14970
1   11549
1   26027
1   2895
1   15052
1   20815
2   9782
2   3393
2   11783
2   22737
2   12102
2   10947
2   24343
2   28620
2   2486
2   249
2   3271
2   30963
2   30532
2   2895
2   13894
2   874
2   2021
3   6720
3   3402
3   25894
3   1290
3   21395
3   21137
3   18739
...
一个小例子

RDD1

RDD2

基于此数据连接结果:

(3-22,1)
(2-21,1)
(3-22,1)
(2-21,1)
(3-22,1)
(4-21,1)
(2-21,1)
(3-21,1)
(3-22,1)
(3-22,1)
(2-21,1)
(3-22,1)
(2-21,1)
(4-21,1)
(2-21,1)
(3-21,1)
REDUCEBYKEY结果:

(4-21,1)
(3-21,1)
(2-21,3)
(3-22,3)

你看过使用笛卡尔连接吗?您可以尝试以下方式:

val rdd1 = sc.parallelize(for { x <- 1 to 3; y <- 1 to 5 } yield (x, y)) // sample RDD
val rdd2 = sc.parallelize(for { x <- 1 to 3; y <- 3 to 7 } yield (x, y)) // sample RDD with slightly displaced values from the first

val g1 = rdd1.groupByKey()
val g2 = rdd2.groupByKey()

val cart = g1.cartesian(g2).map { case ((key1, values1), (key2, values2)) => 
             ((key1, key2), (values1.toSet & values2.toSet).size) 
           }
结果表明,对于(key1,key2),集合之间有3个匹配元素。注意,这里的结果总是3,因为初始化的输入元组的范围由3个元素重叠

笛卡尔变换也不会引起混乱,因为它只是迭代每个RDD的元素并生成笛卡尔乘积。通过调用示例上的
toDebugString()
函数可以看到这一点

scala> val carts = rdd1.cartesian(rdd2)
carts: org.apache.spark.rdd.RDD[((Int, Int), (Int, Int))] = CartesianRDD[9] at cartesian at <console>:25

scala> carts.toDebugString
res11: String =
(64) CartesianRDD[9] at cartesian at <console>:25 []
 |   ParallelCollectionRDD[1] at parallelize at <console>:21 []
 |   ParallelCollectionRDD[2] at parallelize at <console>:21 []
scala>val carts=rdd1.笛卡尔(rdd2)
carts:org.apache.spark.rdd.rdd[((Int,Int),(Int,Int))]=CartesianRDD[9]位于笛卡尔的at:25
scala>carts.toDebugString
res11:字符串=
(64)CartesianRDD[9]位于cartesian at:25[]
|ParallelCollectionRDD[1]在并行化在:21[]
|ParallelCollectionRDD[2]at并行化at:21[]

您应该展示一个使用nano数据的示例,并告诉我spark-default.conf的内容。我刚刚编辑了这个问题。在我工作的地方,集群中有4台8GB的计算机,我们可以毫无问题地读取4GB+文件,所以我打赌您的$spark_HOME/conf/spark-defaults.conf中存在问题,另外,您没有添加我要求的示例,而是使用IN-nano data->OUT-nano data(为了让我们更清楚),我添加了一个小示例。是的,阿尔贝托,我认为我的资料来源必须足以处理这些数据。我在读有关调整spark的文章。我在这里遇到了数据局部性问题。因此,我的文本文件存在于不同的驱动程序中。我的意思是数据在S驱动程序中,而火花在D驱动程序中。那有关系吗?谢谢。很抱歉,这只是让情况变得更糟。@ Zoo323 OOF,是的,我没有考虑记忆的后果。如果较小的数据集有250K条记录,且数据集大致相似,则较大的数据集约有41M条记录。完全笛卡尔计算的容量大约为10TB,这是非常不可行的。这不是唯一的一个<代码> >笛卡尔甚至更糟,即使你只考虑网络流量。一对一连接映射,但笛卡尔乘积映射一对所有。这意味着每个分区都必须移动多次。
(4-21,1)
(3-21,1)
(2-21,3)
(3-22,3)
val rdd1 = sc.parallelize(for { x <- 1 to 3; y <- 1 to 5 } yield (x, y)) // sample RDD
val rdd2 = sc.parallelize(for { x <- 1 to 3; y <- 3 to 7 } yield (x, y)) // sample RDD with slightly displaced values from the first

val g1 = rdd1.groupByKey()
val g2 = rdd2.groupByKey()

val cart = g1.cartesian(g2).map { case ((key1, values1), (key2, values2)) => 
             ((key1, key2), (values1.toSet & values2.toSet).size) 
           }
scala> rdd1.take(5).foreach(println)
...
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
scala> rdd2.take(5).foreach(println)
...
(1,3)
(1,4)
(1,5)
(1,6)
(1,7)
scala> cart.take(5).foreach(println)
...
((1,1),3)
((1,2),3)
((1,3),3)
((2,1),3)
((2,2),3)
scala> val carts = rdd1.cartesian(rdd2)
carts: org.apache.spark.rdd.RDD[((Int, Int), (Int, Int))] = CartesianRDD[9] at cartesian at <console>:25

scala> carts.toDebugString
res11: String =
(64) CartesianRDD[9] at cartesian at <console>:25 []
 |   ParallelCollectionRDD[1] at parallelize at <console>:21 []
 |   ParallelCollectionRDD[2] at parallelize at <console>:21 []