Spark合并vs收集,哪一个更快?

时间:2016-09-15 18:01:34

标签: python apache-spark pyspark

我使用pyspark使用AWS EMR处理50Gb数据,大约15 m4.large核心。

每行数据包含一天中特定时间的某些信息。我使用以下for循环来提取和汇总每小时的信息。最后我union数据,因为我希望我的结果保存在一个 csv文件中。

# daily_df is a empty pyspark DataFrame
for hour in range(24):
    hourly_df = df.filter(hourFilter("Time")).groupby("Animal").agg(mean("weights"), sum("is_male"))
    daily_df = daily_df.union(hourly_df)

据我所知,我必须执行以下操作以强制pyspark.sql.Dataframe对象保存到1个csv文件(大约1Mb)而不是100个以上的文件:

daily_df.coalesce(1).write.csv("some_local.csv")

似乎花了大约70分钟来完成这个进程,我想知道我是否可以通过使用collect()方法来加快速度?

daily_df_pandas = daily_df.collect()
daily_df_pandas.to_csv("some_local.csv")

2 个答案:

答案 0 :(得分:2)

coalesce(1)collect一般都非常糟糕,但预期输出大小约为1MB并不重要。它根本不应成为瓶颈。

一个简单的改进是放弃loop - > filter - > union并执行单个聚合:

df.groupby(hour("Time"), col("Animal")).agg(mean("weights"), sum("is_male"))

如果这还不够,那么这里的问题很可能是配置(如果你不这样做,那么开始的好地方可能是调整spark.sql.shuffle.partitions。)

答案 1 :(得分:2)

要保存为单个文件,这些是选项

选项1: coalesce(1)(网络上的最小随机数据)或repartition(1)或collect可能适用于小型数据集,但可能无法按预期执行大型数据集.since将所有数据移动到一个节点上的一个分区

如果单个执行程序的RAM比驱动程序多,那么

选项1就可以了。

选项2: 其他选项是FileUtil.copyMerge() - 将输出合并为单个文件,如下面的代码片段。

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs._

def merge(srcPath: String, dstPath: String): Unit =  {
  val hadoopConfig = new Configuration()
  val hdfs = FileSystem.get(hadoopConfig)
  FileUtil.copyMerge(hdfs, new Path(srcPath), hdfs, new Path(dstPath), false, hadoopConfig, null)
}

选项3: 获取部分文件后,您可以使用像这样的hdfs getMerge命令...

hadoop fs -getmerge /tmp/demo.csv /localmachine/tmp/demo.csv

现在你必须根据你的要求决定......哪一个更安全/更快

另外,可以查看Dataframe save after join is creating numerous part files