我有这个奇怪的错误。我有一个例程,它读取一个数据帧(如果它存在)(或者另外创建一个),修改它,然后将它再次保存在镶木地板格式的同一目标路径中,并使用'覆盖'模式。
在第一次运行中,当没有数据帧时,我创建一个,然后保存它。它在输出文件夹中生成4个文件:
然后,在第二次运行中,我读取数据帧,修改它,当我尝试覆盖它时,它会引发*part-r-<.....>.snappy.parquet file does not exist*
的异常。
发生异常时输出文件夹为空,但在执行df.write.parquet(path, 'overwrite')
之前,该文件夹包含此文件。
我尝试将spark.sql.cacheMetadata设置为'false',但它没有帮助。 spark.catalog.listTables()返回一个空列表,因此无需刷新任何内容。
现在,我只是删除输出文件夹的项目,并写入数据帧。有用。但为什么带有'覆盖'模式的原始方法失败?
感谢。
答案 0 :(得分:3)
这里要做的另一件事是缓存它 -
df.cache()
从hdfs读取之后。
答案 1 :(得分:2)
RDD并不像变量那样保存数据,它只是一个知道如何获取数据的数据结构(getPartition)以及对该数据执行转换(计算)的内容当操作被调用时。
所以你在这里做的是,
第1次=&gt; ... =&gt;保存到路径A
第二次继续=&gt; 从路径A读取 =&gt;做一些转换=&gt; 使用覆盖模式保存到路径A
现在请注意,您的实际操作是保存到路径A 。使用您调用一个动作,Spark只创建DAG,它知道何时将调用一个动作来查找数据(保存到路径A),如何转换它们以及保存/显示的位置。
但是当你选择模式覆盖时,Spark中的执行计划首先添加删除路径,然后尝试读取已经空缺的路径。
因此,作为一种解决方法,您可以将它们保存为不同的文件夹,例如分区基础,或者您可以将它们保存在两个路径中的一个目标和一个tmp。