如何快速将数据帧/ RDD从PySpark保存为CSV / Parquet文件?

时间:2017-07-31 21:45:31

标签: apache-spark pyspark google-cloud-platform google-cloud-storage google-cloud-dataproc

我正在运行Google Dataproc群集并向其提交PySpark作业,该作业从Google云端存储中读取文件(945MB CSV文件,包含400万行 - >总共需要48秒才能读取)到PySpark Dataframe并将函数应用于该数据帧(parsed_dataframe = raw_dataframe.rdd.map(parse_user_agents).toDF() - >大约需要4或5秒)。

然后我必须将这些修改后的结果作为GZIP的CSV或Parquet文件保存回Google云端存储。我也可以在本地保存这些修改后的结果,然后将它们复制到GCS存储桶中。

我通过parsed_dataframe = parsed_dataframe.repartition(15)重新分区数据框,然后尝试通过

保存新数据框

parsed_dataframe.write.parquet("gs://somefolder/proto.parquet")

parsed_dataframe.write.format("com.databricks.spark.csv").save("gs://somefolder/", header="true")

parsed_dataframe.write.format("com.databricks.spark.csv").options(codec="org.apache.hadoop.io.compress.GzipCodec").save("gs://nyt_regi_usage/2017/max_0722/regi_usage/", header="true")

这些方法中的每一种(以及它们具有较低/较高分区的不同变体以及本地与GCS相比)对于400万行(945 MB)花费超过60分钟,这是相当长的时间。

如何优化此功能/更快地保存数据?

值得注意的是,Dataproc群集和GCS存储桶位于相同的区域/区域中,并且群集具有n1-highmem-8(8CPU,52GB内存)主节点以及15个以上的工作节点(仅变量我还在测试中)

3 个答案:

答案 0 :(得分:3)

这里有一些红旗。

1)作为DF读取然后转换为RDD以进行处理并返回到单独的DF是非常低效的。通过恢复到RDD,您将失去催化剂和钨的优化。尝试将您的功能更改为在DF中工作。

2)重新分区强制进行洗牌但更重要的是意味着计算现在将限于那些控制15个分区的执行者。如果您的执行程序很大(7核,40 GB GB),这可能不是问题。

如果在重新分区之前编写输出会发生什么?

请提供更多代码并理想地激发UI输出以显示作业中每个步骤需要多长时间。

答案 1 :(得分:0)

试试这个,它需要几分钟时间:

your_dataframe.write.csv("export_location", mode="overwrite", header=True, sep="|")

如果要覆盖旧版本,请务必添加mode="overwrite"

答案 2 :(得分:0)

您是否在parsed_dataframe上呼叫action

正如您上面所写,在您致电write之前,Spark不会计算您的功能。如果您未调用某个操作,请查看parsed_dataframe.cache().count()需要多长时间。我怀疑它需要一个小时,然后运行parsed_dataframe.write(...)会更快。