apache-spark - 在写入和重新读取镶木地板文件时保留数据帧分区
问题描述
当我将具有已定义分区的数据帧作为镶木地板文件写入磁盘然后再次重新读取镶木地板文件时,分区将丢失。有没有办法在写入和重新读取期间保留数据帧的原始分区?
示例代码
//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
文件,所以 parquet 文件仍然由 100 个分区组成 - 第三行表示再次读取parquet文件后,原来的分区丢失,读取parquet文件后的分区数量发生变化。分区数和我的Spark集群的executor数有关
- 无论我将 parquet 文件写入本地磁盘还是 Hdfs 存储,结果都是一样的
- 当我运行一个动作时,
readDf
我可以在 SparkUI 中看到创建了四个任务,调用该函数时foreachPartition
执行readDf
了四次
有没有办法在读取 parquet 文件后保留数据帧的原始分区而无需repartition(100)
再次调用?
背景:在我的实际应用程序中,我编写了许多带有仔细调整分区的不同数据集,我想恢复这些分区,而不必为每个数据帧单独记录分区在将它们写入磁盘时的样子。
我正在使用 Spark 2.3.0。
更新:Spark 2.4.6 和 3.0.0 的结果相同
解决方案
推荐阅读
- gstreamer - GStreamer 和 RTSP 流
- azure - 如何筛选 Azure 审核
- reactjs - 如何解决 React 构建的问题
- python - 如何通过 API 从我的 Facebook 帐户获取真实的关注者数量?
- sqlite - 从 SQlit 到 GSheet 的链接?还是 GAS 来导入数据?
- amazon-cloudwatch - 在日志洞察中展开 json
- scala - 在 Scala 中添加到列表
- android - Vue JS 外部 Android 库交互(Zebra)
- java - 从 ElasticSearch Spring 项目中的查询中仅返回嵌套字段
- html - 调整使用 CSS 创建的圆环图