我只是discovered RDD.zip()
方法,我无法想象 其contract 可能是什么。
我理解做什么当然。但是,我的理解一直是
换句话说,RDD是(多)集,而不是序列(当然,在例如Python中,获得{{1} })
我上面的理解有什么问题?
这种方法背后的理由是什么?
在AttributeError: 'set' object has no attribute 'zip'
之类的琐碎背景之外它是否合法?
编辑1:
zipWithIndex()
,以及各种zipPartitions()
变体。first()
和take()
不是疯狂的,因为它们只是RDD的(非随机)样本。 collect()
也没关系 - 它只是将a.map(f).zip(a)
转换为完全合法的set
。编辑2:reply说:
当您从另一个RDD计算一个RDD时,新RDD中的元素顺序可能与旧RDD中的元素顺序不对应。
这似乎意味着,即使是微不足道的sequence
也可以保证等同于a.map(f).zip(a)
。当a.map(x => (f(x),x))
结果可重现时会出现什么情况?
答案 0 :(得分:23)
RDD始终无序是不正确的。例如,如果RDD是sortBy
操作的结果,则RDD具有保证顺序。 RDD不是一组;它可以包含重复项。分区对调用者来说不是不透明的,可以进行控制和查询。许多操作确实保留了分区和顺序,例如map
。这就是说我发现有点容易意外地违反zip
所依赖的假设,因为它们有点微妙,但它肯定有目的。
答案 1 :(得分:8)
我使用(和推荐)的心理模型是RDD 的元素有序,但是当你从另一个RDD计算一个RDD时,新RDD中元素的顺序可能与那个不对应在旧的。
对于那些想要了解分区的人,我会说:
但是,如果你从另一个RDD计算一个RDD,那么关于两个RDD的顺序关系的所有赌注都将被关闭。
RDD类的几个成员(我指的是Scala API)强烈建议订单概念(他们的文档也是如此):
collect()
first()
partitions
take()
zipWithIndex()
Partition.index
以及SparkContext.parallelize()
和SparkContext.makeRDD()
(两者都采用Seq[T]
)。
根据我的经验,这些“观察”顺序的方式给出了彼此一致的结果,并且在RDD和有序Scala集合之间来回转换的行为与您期望的一样 - 它们保留了元素的整体顺序。这就是为什么我说,在实践中,RDD有一个有意义的订单概念。
此外,虽然很明显很多情况下从另一个计算RDD必须改变顺序,但在我的经验顺序中,往往会保留在可能/合理的情况下。不重新分区且不从根本上改变元素集的操作尤其倾向于保持顺序。
但这让我想到了关于“合同”的问题,实际上文档在这方面存在问题。我还没有看到一个操作对元素顺序的影响很明显的地方。 (OrderedRDDFunctions
类不计,因为它引用了基于数据的排序,这可能与RDD中元素的原始顺序不同。同样是RangePartitioner
类。)我可以看到这可能会让你得出结论没有元素顺序的概念,但我上面给出的例子使得这个模型对我不满意。