代码之家  ›  专栏  ›  技术社区  ›  werner

在写入和重新读取拼花文件时保留数据帧分区

  •  2
  • werner  · 技术社区  · 6 年前

    当我将定义了分区的数据帧作为parquet文件写入磁盘,然后重新读取parquet文件时,分区就丢失了。有没有办法在写和重读期间保留数据帧的原始分区?

    示例代码

    //create a dataframe with 100 partitions and print the number of partitions
    val originalDf = spark.sparkContext.parallelize(1 to 10000).toDF().repartition(100)
    println("partitions before writing to disk: " + originalDf.rdd.partitions.length)
    
    //write the dataframe to a parquet file and count the number of files actually written to disk
    originalDf.write.mode(SaveMode.Overwrite).parquet("tmp/testds")
    println("files written to disk: " + new File("tmp/testds").list.size)
    
    //re-read the parquet file into a dataframe and print the number of partitions 
    val readDf = spark.read.parquet("tmp/testds")
    println("partitions after reading from disk: " + readDf.rdd.partitions.length)
    

    partitions before writing to disk: 100
    files written to disk: 202
    partitions after reading from disk: 4
    

    • 第一个数字是预期的结果,数据帧由100个分区组成
    • 第二个数字在我看来也不错:我得到100分 *.parquet 文件,100 *.parquet.crc _SUCCESS 文件,所以拼花文件仍然由100个分区组成
    • 第三行显示再次读取拼花文件后,原始分区将丢失,并且读取拼花文件后的分区数量将更改。分区的数量与Spark集群的执行器的数量有关
    • 无论我将拼花文件写入本地磁盘还是Hdfs存储,结果都是一样的
    • readDf 我可以在SparkUI中看到在调用时创建了四个任务 foreachPartition 该函数执行四次

    有没有一种方法可以保留数据帧的原始分区而不调用 repartition(100)

    背景 :在我的实际应用程序中,我使用经过仔细调整的分区编写了许多不同的数据集,我希望还原这些分区,而不必为每个数据帧单独记录将分区写入磁盘时分区的样子。

    我正在使用Spark 2.3.0。


    更新 :Spark 2.4.6和3.0.0的结果相同

    0 回复  |  直到 4 年前