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

时间:2017-03-05 11:05:59

标签: apache-spark pyspark apache-spark-sql

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

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

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

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

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

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

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

感谢。

2 个答案:

答案 0 :(得分:3)

这里要做的另一件事是缓存它 -

df.cache()

从hdfs读取之后。

答案 1 :(得分:2)

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

所以你在这里做的是,

第1次=&gt; ... =&gt;保存到路径A
第二次继续=&gt; 从路径A读取 =&gt;做一些转换=&gt; 使用覆盖模式保存到路径A

现在请注意,您的实际操作是保存到路径A 。使用您调用一个动作,Spark只创建DAG,它知道何时将调用一个动作来查找数据(保存到路径A),如何转换它们以及保存/显示的位置。

但是当你选择模式覆盖时,Spark中的执行计划首先添加删除路径,然后尝试读取已经空缺的路径。

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