Pyspark:如何将数据帧拆分为多个块并保存?

时间:2020-08-04 13:18:49

标签: python apache-spark pyspark apache-spark-sql pyspark-dataframes

我需要拆分pyspark数据帧df并保存不同的块。

这就是我正在做的:我定义一列id_tmp,然后根据该列拆分数据框。

  chunk = 10000
  id1 = 0
  id2 = chunk
  df = df.withColumn('id_tmp', row_number().over(Window.orderBy(monotonically_increasing_id())) - 1)
  c = df.count()
  while id1 < c:
    stop_df = df.filter( (tmp.id_tmp < id2) & (tmp.id_tmp >= id1))
    stop_df.write.format('com.databricks.spark.csv').save('myFolder/')
    id1+=chunk
    id2+=chunk

有没有更有效的方法而无需定义列id_tmp

1 个答案:

答案 0 :(得分:1)

我建议您使用Spark(docs)内置的partitionBy接口中的DataFrameWriter方法。这是一个例子。

鉴于df数据框,卡盘标识符必须为一列或多列。在我的示例tmp_id中。以下代码段生成了一个DF,其中包含12条记录和4个块ID。

import pyspark.sql.functions as F
df = spark.range(0, 12).withColumn("id_tmp", F.col("id") % 4).orderBy("id_tmp")
df.show() 

返回:

+---+------+
| id|id_tmp|
+---+------+
|  8|     0|
|  0|     0|
|  4|     0|
|  1|     1|
|  9|     1|
|  5|     1|
|  6|     2|
|  2|     2|
| 10|     2|
|  3|     3|
| 11|     3|
|  7|     3|
+---+------+

要独立保存每个块,您需要:

(df
 .repartition("id_tmp")
 .write
 .partitionBy("id_tmp")
 .mode("overwrite")
 .format("csv")
 .save("output_folder"))

repartition将对记录进行混洗,以便每个节点都具有一个“ id_tmp”值的完整记录集。然后使用partitionBy将每个块写入一个文件。

结果文件夹结构:

output_folder/
output_folder/._SUCCESS.crc
output_folder/id_tmp=0
output_folder/id_tmp=0/.part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv.crc
output_folder/id_tmp=0/part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv
output_folder/id_tmp=1
output_folder/id_tmp=1/.part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv.crc
output_folder/id_tmp=1/part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv
output_folder/id_tmp=2
output_folder/id_tmp=2/.part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv.crc
output_folder/id_tmp=2/part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv
output_folder/id_tmp=3
output_folder/id_tmp=3/.part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv.crc
output_folder/id_tmp=3/part-00000-eba244a4-ce95-4f4d-b9b8-8e5f972b144f.c000.csv
output_folder/_SUCCESS

分区的大小和数量对于Spark的性能非常重要。不要对数据集进行过多分区,并且文件大小应合理(例如每个文件1GB),尤其是在使用云存储服务时。如果要在加载时过滤数据(例如:year = YYYY / month = MM / day = DD),也建议使用分区变量