脑洞大开:RDD.zip() 方法
Mind blown: RDD.zip() method
我只是 the RDD.zip()
method and I cannot imagine what its contract 可能是。
我当然明白的作用。然而,我的理解一直是
- RDD 中的元素顺序是一个毫无意义的概念
- 分区的数量及其大小是仅供用户用于性能调整的实现细节
换句话说,一个 RDD 是一个 (multi)set,而不是一个 sequence(而且,当然,在,例如, Python 一人获得 AttributeError: 'set' object has no attribute 'zip'
)
我上面的理解有什么问题吗?
这种方法背后的基本原理是什么?
在像 a.map(f).zip(a)
这样的琐碎上下文之外是否合法?
编辑 1:
- 另一个疯狂的方法是
zipWithIndex()
, as well as well as the various zipPartitions()
变体。
- 请注意
first()
and take()
不是 疯狂,因为它们只是 RDD 的(非随机)样本。
collect()
也可以 - 它只是将 set
转换为完全合法的 sequence
。
编辑 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 中元素的顺序可能与旧版本中的不对应。
对于那些想知道分区的人,我会说:
- 一个RDD的分区是有顺序的。
- 分区中的元素有顺序。
- 如果您使用其中元素的顺序来考虑 "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
所依赖的假设有点容易,因为它们有点微妙,但它肯定有目的。
我只是 RDD.zip()
method and I cannot imagine what its contract 可能是。
我当然明白的作用。然而,我的理解一直是
- RDD 中的元素顺序是一个毫无意义的概念
- 分区的数量及其大小是仅供用户用于性能调整的实现细节
换句话说,一个 RDD 是一个 (multi)set,而不是一个 sequence(而且,当然,在,例如, Python 一人获得 AttributeError: 'set' object has no attribute 'zip'
)
我上面的理解有什么问题吗?
这种方法背后的基本原理是什么?
在像 a.map(f).zip(a)
这样的琐碎上下文之外是否合法?
编辑 1:
- 另一个疯狂的方法是
zipWithIndex()
, as well as well as the variouszipPartitions()
变体。 - 请注意
first()
andtake()
不是 疯狂,因为它们只是 RDD 的(非随机)样本。 collect()
也可以 - 它只是将set
转换为完全合法的sequence
。
编辑 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 中元素的顺序可能与旧版本中的不对应。
对于那些想知道分区的人,我会说:
- 一个RDD的分区是有顺序的。
- 分区中的元素有顺序。
- 如果您使用其中元素的顺序来考虑 "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
所依赖的假设有点容易,因为它们有点微妙,但它肯定有目的。