我使用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")
答案 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将所有数据移动到一个节点上的一个分区
选项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