精神崩溃:RDD.zip()方法

时间:2015-03-25 23:08:03

标签: apache-spark

我只是discovered RDD.zip()方法,我无法想象 contract 可能是什么。

我理解做什么当然。但是,我的理解一直是

  • RDD中元素的顺序是一个毫无意义的概念
  • 分区数及其大小是仅供用户用于性能调整的实现细节

换句话说,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))结果可重现时会出现什么情况?

2 个答案:

答案 0 :(得分:23)

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

答案 1 :(得分:8)

我使用(和推荐)的心理模型是RDD 的元素有序,但是当你从另一个RDD计算一个RDD时,新RDD中元素的顺序可能与那个不对应在旧的。

对于那些想要了解分区的人,我会说:

  1. RDD的分区有订单。
  2. 分区中的元素有订单。
  3. 如果您考虑使用其中元素的顺序“连接”分区(比如按顺序将它们“端到端”),则最终的整体排序对应于忽略分区的元素顺序。
  4. 但是,如果你从另一个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类。)我可以看到这可能会让你得出结论没有元素顺序的概念,但我上面给出的例子使得这个模型对我不满意。