在Scala Spark中,有几种方法可以导致数据分区/重新分区。其中包括partitionBy, coalesce, repartition, and textFile
以及将分区计数作为参数的其他函数。下面,我将textFile
与至少8个分区一起使用。我不希望转换撤消这些分区。为了保留分区,您需要persist
分区结果。但是,诸如map
和flatMap
之类的功能不会保留分区。我相信这可能会影响性能。 PairRDDS具有mapValues and flatMapValues
来维护分区。
DataSets and RDDs
的{{1}}是否具有不破坏分区的等效功能?
如果我把所有这些混淆了,那么RDD和DataSet如何在其中维护分区,请记住map和flatMap操作是它们操作的关键。
map and flatMap
答案 0 :(得分:2)
在Spark中,不重新分区/重新排列数据的操作会保留分区(通过对先前建立的分区进行操作)。 map
和flatMap
就是这样的操作:它们不会更改分区数。此外,map
不会更改分区内的行数或顺序。
RDD和数据集如何在其中维护分区
您正在混淆两个概念:(1)与数据转换相关联的分区程序,以及(2)将数据拆分为的分区。
如何对数据进行分区与将哪个分区与数据相关联之间存在差异。如上所述,map
和flatMap
不会更改分区数,但不能保证与数据关联的分区器。考虑RDD的map
:
/**
* Return a new RDD by applying a function to all elements of this RDD.
*/
def map[U: ClassTag](f: T => U): RDD[U] = withScope {
val cleanF = sc.clean(f)
new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))
}
和MapPartitionsRDD
:
private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](
var prev: RDD[T],
f: (TaskContext, Int, Iterator[T]) => Iterator[U],
preservesPartitioning: Boolean = false, ...)
因此,尽管map
不对数据进行重新分区,但由于与map
修改行的方式没有限制,因此不能保证与数据相关联的分区程序。
对RDD(即RDD[(K, V)]
)有些特殊,因为它们通常是分区操作的结果,如果我们使用mapValues
而不是map
,我们可以确定分区没有更改,因为我们没有触摸“键”。
/**
* Pass each value in the key-value pair RDD through a map function without changing the keys;
* this also retains the original RDD's partitioning.
*/
def mapValues[U](f: V => U): RDD[(K, U)] = self.withScope {
val cleanF = self.context.clean(f)
new MapPartitionsRDD[(K, U), (K, V)](self,
(context, pid, iter) => iter.map { case (k, v) => (k, cleanF(v)) },
preservesPartitioning = true)
}
希望这会有所帮助!