尝试将DataFrame保存为镶木地板格式时,使用'覆盖'模式时出现FileNotFoundException

Mik*_*ike 7 apache-spark apache-spark-sql pyspark

我有这个奇怪的错误.我有一个例程,如果它存在(或者创建一个数据帧),则读取数据帧,修改它,然后使用'overwrite'模式将它再次保存在镶木地板格式的同一目标路径中.

在第一次运行中,当没有数据帧时,我创建一个,然后保存它.它在输出文件夹中生成4个文件:

  • _SUCCESS.crc
  • 部分-R - <.....> snappy.parquet.crc
  • _成功
  • 部分-R - <.....> snappy.parquet

然后,在第二次运行中,我读取数据帧,修改它,当我尝试覆盖它时,它会抛出一个异常*part-r-<.....>.snappy.parquet file does not exist*.

发生异常时输出文件夹为空,但在执行df.write.parquet(path, 'overwrite')文件夹包含此文件之前.

我试图将spark.sql.cacheMetadata设置为'false',但它没有帮助.spark.catalog.listTables()返回一个空列表,因此无需刷新任何内容.

现在,我只是删除输出文件夹的项目,并写入数据帧.有用.但为什么带有'覆盖'模式的原始方法失败?

谢谢.

RBa*_*jee 6

RDD 不像变量那样保存数据,它只是一个数据结构,它知道如何获取数据(getPartition)以及在调用操作时对该数据执行什么转换(计算)

所以你在这里做的是,

第一次 => ... => 保存到路径 A
第二次以后 =>从路径 A 读取=> 进行一些转换 =>使用覆盖模式保存到路径 A

现在请注意,您的实际操作是Save to path A。利用你调用一个动作,Spark 只创建 DAG,它知道什么时候一个动作将被调用,在哪里查找数据(保存到路径 A),如何转换它们以及在哪里保存/显示。

但是当您选择 mode override 时,Spark 在它的执行计划中首先添加删除路径,然后尝试读取已经空置的路径。

因此,作为一种解决方法,您可以将它们保存在不同的文件夹(如分区基础)中,或者您可以将它们保存在两个路径中,一个目的地和一个 tmp。