Apache Spark - dataset.dropDuplicates()是否保留分区?

时间:2018-01-16 11:17:50

标签: scala apache-spark apache-spark-sql

我知道存在几个保留父分区的转换(如果之前已设置 - 例如mapValues),而某些转换则不保留父分区(例如map)。

我使用Spark 2.2的数据集API。我的问题是 - dropDuplicates转换是否保留了分区?想象一下这段代码:

case class Item(one: Int, two: Int, three: Int)

import session.implicits._
val ds = session.createDataset(List(Item(1,2,3), Item(1,2,3)))

val repart = ds.repartition('one, 'two).cache()

repart.dropDuplicates(List("one", "two")) // will be partitioning preserved?

2 个答案:

答案 0 :(得分:4)

通常,dropDuplicates进行随机播放(因此不会保留分区),但在您的特殊情况下,它不会执行额外的随机播放,因为您已经以合适的形式对数据集进行了分区,并考虑了优化器:

repart.dropDuplicates(List("one","two")).explain()

 == Physical Plan ==
*HashAggregate(keys=[one#3, two#4, three#5], functions=[])
+- *HashAggregate(keys=[one#3, two#4, three#5], functions=[])
   +- InMemoryTableScan [one#3, two#4, three#5]
         +- InMemoryRelation [one#3, two#4, three#5], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
               +- Exchange hashpartitioning(one#3, two#4, 200)
                  +- LocalTableScan [one#3, two#4, three#5]

要查找的关键字是:Exchange

但请考虑以下代码,首先使用普通repartition()重新分区数据集:

val repart = ds.repartition(200).cache()
repart.dropDuplicates(List("one","two")).explain()

这确实会引发额外的洗牌(现在你有两个Exchange步骤):

== Physical Plan ==
*HashAggregate(keys=[one#3, two#4], functions=[first(three#5, false)])
+- Exchange hashpartitioning(one#3, two#4, 200)
   +- *HashAggregate(keys=[one#3, two#4], functions=[partial_first(three#5, false)])
      +- InMemoryTableScan [one#3, two#4, three#5]
            +- InMemoryRelation [one#3, two#4, three#5], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
                  +- Exchange RoundRobinPartitioning(200)
                     +- LocalTableScan [one#3, two#4, three#5]

注意:我使用Spark 2.1进行了检查,它在Spark 2.2中可能有所不同,因为Spark 2.2(基于成本的优化程序)中的优化程序已更改

答案 1 :(得分:2)

不,dropDuplicates不保留分区,因为它有一个随机边界,并不能保证顺序。

dropDuplicates约为:

ds.groupBy(columnId).agg(/* take first column from any available partition */)