在spark中,我们有两种操作RDD的方法。
一个是让它尽可能短:
rdd.map(x => h(f(g(x))))
另一个是链,使其更具可读性,如:
rdd.map(g).map(f).map(h)...
我个人喜欢后者,这更清楚。但有些人担心性能,他们认为它与:
相同list.map(g).map(f).map(h)
并且认为在链中会有一些直接的临时RDD,所以他们总是使用前者。
这是真的吗?使用链条有任何性能问题吗?我个人认为它像Stream
,我不认为这两者有很大的性能差异
答案 0 :(得分:3)
这些与流水线代码几乎完全相同。
第一个显而易见的是,当你看起来很清楚时会发生什么,但链接将导致以下(简化):
MapPartitionsRDD(
MapPartitionsRDD(
MapPartitionsRDD(
rdd,
iter.map(g)),
iter.map(f)),
iter.map(h))
进一步简化可视化:
map(map(map(rdd,g),f),h)
执行时归结为:
h(f(g(rddItem)))
好像很熟悉?它只是一系列流水线计算......通过懒惰评估的乐趣带给你。
您可以通过示例看到这一点:
def f(x: Int) = {println(s"f$x");x}
def g(x: Int) = {println(s"g$x");x}
def h(x: Int) = {println(s"h$x");x}
val rdd = sc.makeRDD(1 to 3, 1)
rdd.map(x => h(f(g(x))))
g1
f1
h1
g2
f2
h2
g3
f3
h3
rdd.map(g).map(f).map(h)
g1
f1
h1
g2
f2
h2
g3
f3
h3