脑洞大开:RDD.zip() 方法

Mind blown: RDD.zip() method

我只是 the RDD.zip() method and I cannot imagine what its contract 可能是。

我当然明白的作用。然而,我的理解一直是

换句话说,一个 RDD 是一个 (multi)set,而不是一个 sequence(而且,当然,在,例如, Python 一人获得 AttributeError: 'set' object has no attribute 'zip')

我上面的理解有什么问题吗?

这种方法背后的基本原理是什么?

在像 a.map(f).zip(a) 这样的琐碎上下文之外是否合法?

编辑 1:

编辑 2: 说:

when you compute one RDD from another the order of elements in the new RDD may not correspond to that in the old one.

这似乎意味着即使是微不足道的 a.map(f).zip(a) 而不是 保证等同于 a.map(x => (f(x),x)) .当zip()结果可重现时是什么情况?

我使用(并推荐)的思维模型是 RDD 的元素是 有序的,但是当你从一个 RDD 计算另一个 RDD 时,新 RDD 中元素的顺序可能与旧版本中的不对应。

对于那些想知道分区的人,我会说:

  1. 一个RDD的分区是有顺序的。
  2. 分区中的元素有顺序。
  3. 如果您使用其中元素的顺序来考虑 "concatenating" 分区(比如按顺序 "end to end" 放置它们),则您最终得到的整体顺序对应于元素的顺序,如果你忽略分区。

但同样,如果您从一个 RDD 计算另一个 RDD,则所有关于两个 RDD 的顺序关系的赌注都将被取消。

RDD 的几个成员class(我指的是 Scala API)强烈建议使用顺序概念(他们的文档也是如此) :

collect()
first()
partitions
take()
zipWithIndex()

Partition.index 以及 SparkContext.parallelize()SparkContext.makeRDD() 一样(两者都采用 Seq[T])。

根据我的经验,这些 "observing" 排序方式给出的结果彼此一致,并且在 RDD 和有序 Scala 集合之间来回转换的方式的行为与您预期的一样——它们保留了元素的整体顺序。这就是为什么我说,在实践中,RDD 有一个有意义的顺序概念。

此外,虽然在很多情况下从另一个 计算一个 RDD 必须 改变顺序,但根据我的经验,顺序往往会保留在原处 possible/reasonable这样做。不重新分区且不从根本上改变元素集的操作特别倾向于保持顺序。

但这让我想到了你关于 "contract" 的问题,确实文档在这方面存在问题。我还没有看到一个地方可以清楚地说明操作对元素顺序的影响。 (OrderedRDDFunctions class 不算数,因为它指的是基于数据的排序,这可能与 RDD 中元素的原始顺序不同。同样 RangePartitioner class.) 我可以看出这可能如何让您得出结论,即没有 没有 元素顺序的概念,但我上面给出的示例使该模型对我来说并不令人满意。

RDD 总是无序的说法是不正确的。例如,如果 RDD 是 sortBy 操作的结果,则它具有保证顺序。 RDD 不是集合;它可以包含重复项。分区对调用者来说不是不透明的,可以控制和查询。许多操作确实保留了分区和顺序,例如 map。也就是说,我发现意外违反 zip 所依赖的假设有点容易,因为它们有点微妙,但它肯定有目的。