Spark - 如何在N个分区上进行计算,然后写入1个文件

时间:2016-05-13 17:15:55

标签: apache-spark pyspark

我想在许多分区上进行计算,从并行性中受益,然后将我的结果写入单个文件,可能是镶木地板文件。我在PySpark 1.6.0中尝试过的工作流程如下:

data_df = sqlContext.read.load('my_parquet_file')
mapped_df = sqlContext.createDataFrame(data_df.map(lambda row: changeRow(row)), ['c1', 'c2'])
coalesced_df = mapped_df.coalesce(1)
coalesced_df.write.parquet('new_parquet_file')

但是从看看Spark的Web UI看来,所有的工作,包括map部分都发生在一个线程上。

有没有办法调整这个以便map在许多分区上发生而write仅在1上发生?我认为唯一可行的方法是在mapped_df.count()map之间加coalesce,但这并不是一种令人满意的方式。这样做。

2 个答案:

答案 0 :(得分:2)

Spark做懒惰评估意味着在调用动作之前它不会执行任何操作。 writecount都是 tricker执行的操作。像mapfilter这样的函数很容易执行执行某些操作 - 而不是之前执行某些操作。

现在,您的管道非常简单,只有一个操作(write),因此在编写文件时正在执行 {em}。然而,通过调用map,您还可以告诉Spark在执行coalesce(1)操作之前将所有数据收集到一个分区中,并且因为write是其中的一部分。在map操作中执行,write也将在一个分区中运行。

我希望这是有道理的。我建议你也阅读一些关于Spark如何工作的博客文章。来自Cloudera的This one,应该给你一些见解:)

答案 1 :(得分:1)

您想使用“repartition(1)”而不是“coalesce(1)”。问题在于“重新分配”将很乐意改变以实现其目的,而“合并”则不会。

“Coalesce”比“repartition”更有效,但必须谨慎使用,否则并行性最终将受到严重限制。所有分区“合并”合并到特定结果分区必须驻留在同一节点上。 “coalesce(1)”调用需要单个结果分区,因此“mapped_df”的所有分区都需要驻留在单个节点上。为了实现这一点,Spark鞋子将“mapped_df”变成了一个分区。