关于性能与可读性的公开奖励让我想知道:之间有什么区别:
val df: DataFrame = ...
val final = df.filter(...).select(...)
和
val df: DataFrame = ...
val filtered = df.filter(...)
val final = filtered.select(...)
在表现方面?同样适用于RDD
- 如果我执行RDD.filter
并将结果分配给val
然后执行RDD.map
,那么中间分配是否有成本?
我不知道为什么,但我有这种模糊的信念,认为这些会导致不必要的开销。
都市神话还是已确认?
答案 0 :(得分:3)
我能想到的唯一开销是创建一个val
,指向驱动程序上的RDD
。不确定Scala需要多少ms; - )
首先在你的例子中,没有任何事情会发生,因为你没有让Spark提交任何工作。工作仅在行动时提交(即collect()
等)。您显示的任务只是声明一个RDD,但不会触发任何操作。
由于上述所有RDD都可以延迟,因此您无需计算任何内容。
当您提交作业时,Spark会创建任务(filter,map,reduce,groupByKey等)的有向无环图(DAG),这些图必须是为完成工作而执行:-)有两种类型的任务:狭窄和宽。广泛的任务需要数据随机播放。如果需要任何随机播放,Spark会将你的任务分成阶段,即第一阶段将在shuffle之前完成所有任务,第二阶段将在shuffle之后完成所有任务。
感谢这个Spark,在运行任何东西之前,实际上可以将你上面发布的调用压缩到一个可以在同一个分区上运行的阶段(整个过滤器 - >选择链)。
val df: DataFrame = ...
val filtered = df.filter(...)
val final = filtered.select(...)
final.collect()
Spark将在内部为final
RDD创建一个沿袭,并确定filter()
和select()
可以并行化(同样也会检查缓存)并在同一个分区上一起运行。两种情况下的血统应该与collect()
相同。
有关Spark内部的一些很酷的讨论,例如this或this one from Spark Summit 2014。