Spark中“join”和“union”后跟“groupByKey”的区别?
我找不到一个好的理由:Spark中“join”和“union”后跟“groupByKey”的区别?,join,apache-spark,group-by,union,pyspark,Join,Apache Spark,Group By,Union,Pyspark,我找不到一个好的理由: anRDD.join(anotherRDD) 应不同于: anRDD.union(anotherRDD).groupByKey() 但是,后者给了我一个错误,而前者没有。如果绝对需要,我可以提供一个例子,但我想从功能抽象的角度来了解。我问过的任何人都不能很好地解释这一点。前者和后者有不同的结果集: 前任: (K, V).join(K, W) = (K, (V, W)) 前者的结果是equi-join,SQL类比: anRDD.K = anotherRDD.K
anRDD.join(anotherRDD)
应不同于:
anRDD.union(anotherRDD).groupByKey()
但是,后者给了我一个错误,而前者没有。如果绝对需要,我可以提供一个例子,但我想从功能抽象的角度来了解。我问过的任何人都不能很好地解释这一点。前者和后者有不同的结果集:
- 前任:
前者的结果是equi-join,SQL类比:(K, V).join(K, W) = (K, (V, W))
anRDD.K = anotherRDD.K
- 后者: 不仅包括相等联接结果,还包括来自anRDD的并集不匹配部分和另一个RDD的不匹配部分
- 前任:
前者的结果是equi-join,SQL类比:(K, V).join(K, W) = (K, (V, W))
anRDD.K = anotherRDD.K
- 后者: 不仅包括相等联接结果,还包括来自anRDD的并集不匹配部分和另一个RDD的不匹配部分
与两个RDD一起工作,每个RDD由对组成,并且具有需要匹配的相同密钥。两个RDD的值类型不需要匹配。生成的rdd将包含类型为(Key,(Value1,Value2))的条目join
- 如果
和anRDD
具有不同类型的值,则anotherRDD
anRDD.union(anotherRDD).groupByKey()将产生错误;如果键和值的类型相同,则不会产生错误。结果将是类型为(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
编辑:OP使用的是Python,而不是Scala。Python和Scala在类型安全性方面存在差异。Scala将捕获两个RDD之间的类型不匹配,如上图所示;Python不会立即捕获它,但稍后当您尝试在错误类型的对象上应用方法时会产生隐藏的错误。记住,Spark是用Scala和Python API编写的
事实上,我在注释中尝试了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):
以下是我将用以下代码说明的一些要点:
与两个RDD一起工作,每个RDD由对组成,并且具有需要匹配的相同密钥。两个RDD的值类型不需要匹配。生成的rdd将包含类型为(Key,(Value1,Value2))的条目join
- 如果
和anRDD
具有不同类型的值,则anotherRDD
anRDD.union(anotherRDD).groupByKey()将产生错误;如果键和值的类型相同,则不会产生错误。结果将是类型为(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
编辑:OP使用的是Python,而不是Scala。Python和Scala在类型安全性方面存在差异。Scala将捕获两个RDD之间的类型不匹配,如上图所示;Python不会立即捕获它,但稍后当您尝试在错误类型的对象上应用方法时会产生隐藏的错误。记住,Spark是用Scala和Python API编写的
事实上,我在注释中尝试了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):
依我看,用数据来举例总是更好的。因为join处理pairsIMHO,所以最好提供数据示例。自从join与Pairs打交道以来,我用两个RDD尝试了一个
union
和groupByKey
,每个RDD都有不同的值类型,它没有给我一个错误:B=('B',[1]),('c',[0])
,c=('B',['bs']),('rdc',['cs'])
,anRDD=sc.parallelize(B),,anotherd=sc.parallelize(c)
,B_C_unionRDD=anRDD.union(另一个rdd.groupByKey()
。它不会抛出错误。我理解您关于连接
的结果是元组,而联合
-分组键
的结果是可数的观点。但即使我将iterable放入列表中(list())< /代码>,似乎不应该有任何区别。我编辑了斯卡拉和Python之间的类型安全性差异的答案。如果你觉得有用的话,请考虑一下投票。我尝试了一个<代码>联合<代码>和<代码> GypByKEY < /C> >两个RDDS,每个RDDS都有不同的值类型,并且不给我一个错误:<代码> B=((b),[1 ]),(c),[0])
,C=(('b',['bs']),('C',['cs'])
,anRDD=sc.parallelize(b)
,anotherRDD=sc.parallelize(C)
,b_C_unionRDD=anRDD.union(anotherRDD.groupByKey)()
。它不会抛出错误。我理解您关于联接的结果是元组,以及联合的结果是iterable的观点。但即使我将iterable放入列表中(列表(),似乎不应该有任何区别。我编辑了斯卡拉和Python之间的类型安全性差异的答案。如果你觉得它有用的话,请考虑一下投票。