当我将定义了分区的数据帧作为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的结果相同