在Spark中,`join`和`union`之间的区别是`groupByKey`?

时间:2015-12-13 08:20:31

标签: join apache-spark group-by union pyspark

我找不到一个好理由:

Subgroup2
=========

Subgroup2 contents

应该与:

不同
anRDD.join(anotherRDD)

但是,后者给了我一个错误而前者没有。如果绝对需要,我可以提供一个例子,但我想从功能抽象的角度来了解。没有人问我可以给我一个很好的解释。

2 个答案:

答案 0 :(得分:3)

以下是一些我将通过以下代码说明的要点:

  • join使用两个rdds,每个rdds由成对组成,并且具有需要匹配的相同键。不需要匹配两个rdds的值的类型。生成的rdd将具有类型(Key,(Value1,Value2))
  • 的条目 如果anRDD.union(anotherRDD).groupByKey()anRDD具有不同类型的值,则
  • anotherRDD会产生错误;如果键和值具有相同类型,则不会产生错误。结果将是类型(Key,Iterable [Value])的条目,其中Iterable不需要像join一样具有长度2。

示例:

val rdd1 = sc.parallelize(Seq(  ("a", 1) , ("b", 1)))
val rdd2 = sc.parallelize(Seq(  ("a", 2) , ("b", 2)))
val rdd3 = sc.parallelize(Seq(  ("a", 2.0) , ("b", 2.0))) // different Value type
val rdd4 = sc.parallelize(Seq(  ("a", 1) , ("b", 1), ("a", 5) , ("b", 5)))
val rdd5 = sc.parallelize(Seq(  ("a", 2) , ("b", 2), ("a", 5) , ("b", 5)))

产生以下内容:

scala> rdd1.join(rdd2)
res18: org.apache.spark.rdd.RDD[(String, (Int, Int))] = MapPartitionsRDD[77] at join at <console>:26

scala> rdd1.union(rdd2).groupByKey
res19: org.apache.spark.rdd.RDD[(String, Iterable[Int])] = ShuffledRDD[79] at groupByKey at <console>:26

scala> rdd1.union(rdd3).groupByKey
<console>:26: error: type mismatch;
 found   : org.apache.spark.rdd.RDD[(String, Double)]
 required: org.apache.spark.rdd.RDD[(String, Int)]
              rdd1.union(rdd3).groupByKey

如果你在你的rdds中有重复的键,请注意产生不同的结果:

scala> rdd4.union(rdd5).groupByKey.collect.mkString("\n")
res21: String = 
(a,CompactBuffer(1, 5, 2, 5))
(b,CompactBuffer(1, 5, 2, 5))

scala> rdd4.join(rdd5).collect.mkString("\n")
res22: String = 
(a,(1,2))
(a,(1,5))
(a,(5,2))
(a,(5,5))
(b,(1,2))
(b,(1,5))
(b,(5,2))
(b,(5,5))

编辑:OP使用的是Python,而不是Scala。 Python和Scala之间的类型安全性存在差异。如上所示,Scala将捕获两个RDD之间类型不匹配的事情; Python不会马上捕获它,但是当你尝试在错误类型的对象上应用方法时,Python会产生神秘的错误。请记住,Spark是使用Python API在Scala中编写的。

确实,我在评论中尝试了OP代码,而在pyspark中,它适用于count()之类的简单操作。但是,如果您尝试对每个值(可以对整数执行,但不对字符串执行)进行平方,则会产生错误。

这是数据:注意我省略了列表,我只有值1和0。

B = [('b',1), ('c',0)]
C = [('b', 'bs'), ('c', 'cs')]
anRDD = sc.parallelize(B)
anotherRDD = sc.parallelize(C)

这是输出:

>>> anRDD.join(anotherRDD).count()
2
>>> anRDD.union(anotherRDD).groupByKey().count()
2
>>> for y in anRDD.map(lambda (a, x): (a, x*x)).collect():
...   print y
... 
('b', 1)
('c', 0)
>>> for y in anRDD.union(anotherRDD).map(lambda (a, x): (a, x*x)).collect():
...   print y
... 
15/12/13 15:18:51 ERROR Executor: Exception in task 5.0 in stage 23.0 (TID 169)
org.apache.spark.api.python.PythonException: Traceback (most recent call last):

答案 1 :(得分:1)

前者和后者有不同的结果集:

  • 前任:

    (K, V).join(K, W) = (K, (V, W))
    

    前一个结果是equi-join,SQL类比:

    anRDD.K = anotherRDD.K
    
  • 后期:

    不仅包括等连接结果,还包括来自anRDD和非匹配部分另一个RDD的联合非匹配部分。