保存到增量表时,我们避免使用“df.coalesce(1)”,但保存到 csv 或 parquet 时,我们(我的团队)添加“df.coalesce(1)”。这是一种常见的做法吗?为什么?是强制性的吗?
最佳答案
大多数情况下,当我看到df.coalesce(1)
时这样做是为了仅生成一个文件,例如,将 CSV 文件导入 Excel,或者将 Parquet 文件导入基于 Pandas 的程序。但如果你正在做.coalesce(1)
,那么写入是通过单个任务进行的,并且它正在成为性能瓶颈,因为您需要从其他执行器获取数据,然后写入。
如果您使用来自 Spark 或其他分布式系统的数据,拥有多个文件将有利于性能,因为您可以并行写入和读取它们。默认情况下,Spark 将 N 个文件写入目录,其中 N 是分区数。如@pltc请注意,这可能会生成大量文件,这通常是不需要的,因为访问它们会带来性能开销。因此,我们需要在文件数量和文件大小之间取得平衡 - 对于 Parquet 和 Delta(基于 Parquet),更大的文件会带来一些性能优势 - 读取的文件更少,可以对内部数据获得更好的压缩文件等
特别是对于达美航空来说,有 .coalesce(1)
与其他文件格式有同样的问题 - 您正在通过一项任务进行写入。从性能角度来看,依赖 Spark 默认行为并写入多个文件是有益的 - 每个节点都并行写入其数据,但您可能会获得太多小文件(因此您可以使用 .coalesce(N)
来写入更大的文件)。对于 Databricks Delta,因为 @Kafels 正确指出了它,有some optimizations这将允许删除 .coalesce(N)
并自动调整以实现最佳吞吐量(所谓的“优化写入”),并创建更大的文件(“自动压缩”) - 但应谨慎使用它们。
总的来说,Delta 的最佳文件大小是一个有趣的话题 - 如果您有大文件(OPTIMIZE 命令默认使用 1Gb),您可以获得更好的读取吞吐量,但如果您使用 MERGE 重写它们/UPDATE/DELETE,那么从性能角度来看大文件是不好的,最好有较小的(16-64-128Mb)文件,这样你就可以重写更少的数据。
关于apache-spark - 在 csv 与 delta 表中使用 df.coalesce(1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67540178/