Apache spark Distinct()函数在Spark中如何工作?

Apache spark Distinct()函数在Spark中如何工作?,apache-spark,distinct,Apache Spark,Distinct,我是Apache Spark的新手,正在学习基本功能。 我有一个小小的疑问。假设我有一个元组(key,value)的RDD,并希望从中获得一些唯一的元组。我使用distinct()函数。我想知道函数在什么基础上认为元组是不同的?它是基于键还是基于值,还是基于两者?的API文档仅提供一句话的描述: “返回包含此RDD中不同元素的新RDD。” 根据最近的经验,我可以告诉你,在元组RDD中,元组作为一个整体被考虑 如果您想要不同的键或不同的值,则根据您想要完成的内容,您可以: A.调用groupByK

我是Apache Spark的新手,正在学习基本功能。 我有一个小小的疑问。假设我有一个元组(key,value)的RDD,并希望从中获得一些唯一的元组。我使用distinct()函数。我想知道函数在什么基础上认为元组是不同的?它是基于键还是基于值,还是基于两者?

的API文档仅提供一句话的描述:

“返回包含此RDD中不同元素的新RDD。”

根据最近的经验,我可以告诉你,在元组RDD中,元组作为一个整体被考虑

如果您想要不同的键或不同的值,则根据您想要完成的内容,您可以:

A.调用
groupByKey()
{(k1,v11)、(k1,v12)、(k2,v21)、(k2,v22)}
转换为
{(k1,[v11,v12]),(k2,[v21,v22])
;或

B.通过调用
keys()
values()
然后调用
distinct()


在撰写本文(2015年6月)时,加州大学伯克利分校+EdX正在运行一个免费的在线课程,该课程将提供这些功能的实践。

distinct
使用对象的
hashCode
equals
方法进行此确定。元组内置了平等机制,将平等和位置委托给每个对象。因此,
distinct
将对整个
Tuple2
对象起作用。正如Paul指出的,您可以调用
,然后调用
distinct
。或者,您可以通过
aggregateByKey
编写自己的不同值,这将保持密钥配对。或者,如果您想要不同的键,那么您可以使用常规的
聚合
.distinct()
确实是在分区之间进行随机移动。要查看更多正在发生的情况,请在RDD上运行
.toDebugString

val hashPart = new HashPartitioner(<number of partitions>)

val myRDDPreStep = <load some RDD>

val myRDD = myRDDPreStep.distinct.partitionBy(hashPart).setName("myRDD").persist(StorageLevel.MEMORY_AND_DISK_SER)
myRDD.checkpoint
println(myRDD.toDebugString)
请注意,可能有更有效的方法来获得不同的结果,其中涉及的洗牌次数更少,特别是如果您的RDD已经以智能方式进行了分区,并且分区没有过度倾斜

看 和

看起来,
独立的
将消除(键、值)重复项

在下面的示例中,(1,20)和(2,20)在
myRDD
中重复两次,但在
distinct()
之后,重复项被删除

scala> val myRDD = sc.parallelize(List((1,20), (1,21), (1,20), (2,20), (2,22), (2,20), (3,21), (3,22)))
myRDD: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[1274] at parallelize at <console>:22

scala> myRDD.collect().foreach(println _)
(1,20)
(1,21)
(1,20)
(2,20)
(2,22)
(2,20)
(3,21)
(3,22)

scala> myRDD.distinct.collect().foreach(println _)
(2,22)
(1,20)
(3,22)
(2,20)
(1,21)
(3,21)
scala>val myRDD=sc.parallelize(列表((1,20)、(1,21)、(1,20)、(2,20)、(2,22)、(2,20)、(3,21)、(3,22)))
myRDD:org.apache.spark.rdd.rdd[(Int,Int)]=ParallelCollectionRDD[1274]at parallelize at:22
scala>myRDD.collect().foreach(println\ux)
(1,20)
(1,21)
(1,20)
(2,20)
(2,22)
(2,20)
(3,21)
(3,22)
scala>myRDD.distinct.collect().foreach(println\ux)
(2,22)
(1,20)
(3,22)
(2,20)
(1,21)
(3,21)

贾斯汀·皮奥尼是对的。Distinct使用对象的hashCode和equals方法进行此确定。它返回不同的元素(对象)

明显的

rdd.distinct.collect().foreach(println)
(2,22)
(1,20)
(3,22)
(2,20)
(1,21)
(3,21)
如果要在键上应用distinct。 在这种情况下,减少是更好的选择

还原比

 val reduceRDD= rdd.map(tup =>
    (tup._1, tup)).reduceByKey { case (a, b) => a }.map(_._2)

reduceRDD.collect().foreach(println)
输出:-

(2,20)
(1,20)
(3,21)

嗨,保罗!假设我们有一个RDD元组,如下所示:(1,20),(1,21),(1,20),(2,20),(2,22),(2,20),(3,21),(3,22)…等等,这里您可以观察到键和值都在不同的元组中重复。因此,如果我在上面的RDD上应用distinct(),结果会是什么。。?请稍等片刻。非常感谢。而且,是的,我正在网上学习这门课程!:)我现在没有时间,但您可以使用
myRDD=sc.parallelize([(1,20),(1,21),(1,20),(2,20),(2,22),(2,20),(3,21),(3,22)])来设置自己的RDD这甚至可以在Spark课程之前的一本实验笔记本中使用。然后运行
myRDD.distinct().collect()测试输出
 val reduceRDD= rdd.map(tup =>
    (tup._1, tup)).reduceByKey { case (a, b) => a }.map(_._2)

reduceRDD.collect().foreach(println)
(2,20)
(1,20)
(3,21)