我正在使用sql spark通过以下代码在hdfs中读取和写入文件:
val df = spark.read.parquet("D:/resources/input/address/year_month_day=2018-07-02")
val df.write.mode("overwrite").parquet("D:/resources/output/t_kcdo_person")
写作的结果很多 files 。根据我所学的知识,不建议文件的大小小于128 MB。我一直在寻找减少文件数量但增大文件大小的方法,并且找到了df.coalesce函数,但是我有一个问题是否建议使用此函数,因为这样可以避免并行性。
答案 0 :(得分:0)
这是Spark中的一个已知问题。无论数据的实际大小如何,每个分区都会输出一个文件。 coalesce
也不是灵丹妙药-您需要非常小心分区的新数目-分区太小,应用程序将OOM。您可能会考虑在运行时计算合并值,但是在大多数情况下,这意味着将数据持久保存到磁盘中,获取实际大小,然后再次读取,然后coalesce
达到最佳大小。
在您的简单示例中,您可以预先获取实际的输入大小。但是对于一般情况,有FileCrush之类的工具可在您的输出(小的文件)上运行并将它们合并为更少的文件。但是它现在很旧,并且基于map-reduce(尽管仍然有效)。在我们的团队中,我们构建了一个非常简单的Spark版本,您可以轻松创建自己的版本。如果这样做,在计算最佳分区数量时,请记住考虑使用压缩编解码器。
此外,使用coalesce
时担心并行性是正确的。如果这成为问题,并且您在coalesce
之前有一些应在更高级别的并行度上运行的计算,则可以使用spark.createDataFrame(df.rdd, df.schema)
之类的东西来创建新的数据框并避免获取{{1 }}推得太低。但是,这具有重要的含义,您需要考虑。