开始使用pyspark并遇到我用我的代码创建的瓶颈:
我" m"按"分组通过drive_id将pyspark 2.2.0数据帧划分为分区 并将每个分区(组)写入S3上的自己的位置。
我需要它来定义由drive_id分区的S3位置上的Athena表 - 如果被drive_id查询,这可以让我非常有效地读取数据。
#df is spark dataframe
g=df.groupBy(df.drive_id)
rows=sorted(g.count().collect())
#each row is a parition
for row in rows:
w=df.where((col("drive_id") == row.drive_id))
w.write.mode('append').parquet("s3n://s3bucket/parquet/drives/"+str(table)+"/drive_id="+str(row.drive_id) )
问题是循环使处理串行并且只逐个写入驱动器分区。
显然,这并不能很好地扩展,因为单个分区写入任务非常小并且并行化它并不能给予很多。
如何使用单一写入命令替换循环,在单次操作中将所有分区写入不同的位置?
此操作应该并行运行在spark worker上,而不是驱动程序。
答案 0 :(得分:3)
我找到了答案 - 非常简单。
dataframe.write.parquet有可选参数partitionBy(names_of_partitioning_columns)。
所以"组中没有必要"并且不需要循环: 使用单行:
df.write.partitionBy(drive_id).parquet("s3n://s3bucket/dir")
以标准配置单元格式创建分区" s3n:// s3bucket / dir / drive_id = 123"