Distinct()函数如何在Spark中运行?

时间:2015-06-20 23:47:14

标签: apache-spark distinct

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

5 个答案:

答案 0 :(得分:22)

.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示例(myRDDPreStep已经被密钥哈希分区,由StorageLevel.MEMORY_AND_DISK_SER持久化,并且检查点),返回:

(2568) myRDD ShuffledRDD[11] at partitionBy at mycode.scala:223 [Disk Memory Serialized 1x Replicated]
+-(2568) MapPartitionsRDD[10] at distinct at mycode.scala:223 [Disk Memory Serialized 1x Replicated]
    |    ShuffledRDD[9] at distinct at mycode.scala:223 [Disk Memory Serialized 1x Replicated]
    +-(2568) MapPartitionsRDD[8] at distinct at mycode.scala:223 [Disk Memory Serialized 1x Replicated]
        |    myRDDPreStep ShuffledRDD[6] at partitionBy at mycode.scala:193 [Disk Memory Serialized 1x Replicated]
        |        CachedPartitions: 2568; MemorySize: 362.4 GB; TachyonSize: 0.0 B; DiskSize: 0.0 B
        |    myRDD[7] at count at mycode.scala:214 [Disk Memory Serialized 1x Replicated]

请注意,如果您的RDD已经以智能方式分区且分区不会过度倾斜,可能会有更有效的方法来获得涉及更少shuffle的独特方式。

参见Is there a way to rewrite Spark RDD distinct to use mapPartitions instead of distinct?Apache Spark: What is the equivalent implementation of RDD.groupByKey() using RDD.aggregateByKey()?

答案 1 :(得分:10)

RDD.distinct()的API文档仅提供一句话描述:

  

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

从最近的经验我可以告诉你,在一个元组-RDD中,整个元组被认为是。

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

一个。致电groupByKey(){(k1,v11),(k1,v12),(k2,v21),(k2,v22)}转换为{(k1,[v11,v12]), (k2,[v21,v22])};或

B中。通过调用keys()values()后跟distinct()

来删除键或值

截至撰写本文时(2015年6月),加州大学伯克利分校+ EdX正在开设免费在线课程Introduction to Big Data and Apache Spark,该课程将提供实践这些功能。

答案 2 :(得分:7)

Justin Pihony是对的.Distinct使用对象的hashCode和equals方法进行此确定。它返回不同的元素(对象)

val rdd = sc.parallelize(List((1,20), (1,21), (1,20), (2,20), (2,22), (2,20), (3,21), (3,22)))

鲜明

rdd.distinct.collect().foreach(println)
(2,22)
(1,20)
(3,22)
(2,20)
(1,21)
(3,21)

如果要在密钥上应用distinct。 在这种情况下,减少是更好的选择

ReduceBy

 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)

答案 3 :(得分:4)

distinct使用对象的hashCodeequals方法进行此确定。元组内置于等式机制,分配到每个对象的相等和位置。因此,distinct将对整个Tuple2对象起作用。正如保罗指出的那样,您可以拨打keysvalues,然后拨打distinct。或者您可以通过aggregateByKey编写自己的不同值,这将保持密钥配对。或者,如果您需要不同的密钥,则可以使用常规aggregate

答案 4 :(得分:3)

看起来obj1 | obj2 someName; 将摆脱(键,值)重复。

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

distinct()