Scala Spark RDD,数据集,PairRDD和Partitoning

时间:2019-01-23 02:56:54

标签: scala apache-spark rdd apache-spark-dataset

在Scala Spark中,有几种方法可以导致数据分区/重新分区。其中包括partitionBy, coalesce, repartition, and textFile以及将分区计数作为参数的其他函数。下面,我将textFile与至少8个分区一起使用。我不希望转换撤消这些分区。为了保留分区,您需要persist分区结果。但是,诸如mapflatMap之类的功能不会保留分区。我相信这可能会影响性能。 PairRDDS具有mapValues and flatMapValues来维护分区。

DataSets and RDDs的{​​{1}}是否具有不破坏分区的等效功能?

如果我把所有这些混淆了,那么RDD和DataSet如何在其中维护分区,请记住map和flatMap操作是它们操作的关键。

map and flatMap

Below is a screenshot from a youtube video stating that a map in a pairRDD results in an RDD without a partitioner

1 个答案:

答案 0 :(得分:2)

在Spark中,不重新分区/重新排列数据的操作会保留分区(通过对先前建立的分区进行操作)。 mapflatMap就是这样的操作:它们不会更改分区数。此外,map不会更改分区内的行数或顺序。

  

RDD和数据集如何在其中维护分区

您正在混淆两个概念:(1)与数据转换相关联的分区程序,以及(2)将数据拆分为的分区。

如何对数据进行分区与将哪个分区与数据相关联之间存在差异。如上所述,mapflatMap不会更改分区数,但不能保证与数据关联的分区器。考虑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)
}

希望这会有所帮助!