无法在 pyspark 中覆盖镶木地板配置单元 table
Failing to overwrite parquet hive table in pyspark
使用:火花 1.5.2,蜂巢 1.2
我有一个镶木地板格式的外部配置单元 table。我创建了一个 .py 脚本,它从 my_table 中选择一个数据帧,进行一些转换,然后尝试写回原始 table。
我试过以下方法:
df.write.insertInto('table_name', overwrite='true')
。
这会引发以下错误:
pyspark.sql.utils.AnalysisException: Cannot insert overwrite into table that is also being read from.
df.write.mode('overwrite').parquet('my_path')
df.write.parquet('my_path', mode='overwrite')
df.write.save('my_path', format='parquet', mode = 'overwrite')
这些似乎都抛出了这个错误:
ERROR Client fs/client/fileclient/cc/client.cc:1802 Thread: 620 Open failed for file /my_path/part-r-00084-9, LookupFid error No such file or directory(2)
2016-04-26 16:47:17,0942 ERROR JniCommon fs/client/fileclient/cc/jni_MapRClient.cc:2488 Thread: 620 getBlockInfo failed, Could not open file /my_path/part-r-00084-9
16/04/26 16:47:17 WARN DAGScheduler: Creating new stage failed due to exception - job: 16
**请注意,如果文件格式是 orc,上面的方法 1 工作正常,但对于 parquet 会抛出该错误。
如有任何建议,我们将不胜感激!
从我目前发现的所有内容来看,读取和写入 parquet 格式文件的解决方案似乎是写入 temporary/staging 目录,删除原始目录,然后重命名临时目录到你原来的目录。
要在 pyspark 中执行此操作,您将需要以下命令:
import os
import shutil
shutil.rmtree('my_tmp_path')
os.rename('my_tmp_path', 'my_path)
为此你需要使用一个临时路径来写入。
问题是 Spark 主动使用实际路径读取数据,当您尝试写入同一个 parquet 文件时,它会生成错误。
Stella 已经给出了 应该做什么,但顺序不对。所以我决定给你一个更好更完整的答案,因为我必须自己解决它:
在下面的代码中,我尝试使用临时文件保存数据框:
def write_dataframe(df, table_name):
# caches dataframe
df.cache()
dirout_tmp = PATH + table_name + "_tmp/"
dirout = PATH + table_name + "/"
# writing parquet file to a temporary location
df.write.parquet(dirout_tmp, mode='overwrite')
# removing original parquet
shutil.rmtree(dirout, ignore_errors=True)
# renaming the temp to the original path
os.rename(dirout_tmp, dirout)
使用:火花 1.5.2,蜂巢 1.2 我有一个镶木地板格式的外部配置单元 table。我创建了一个 .py 脚本,它从 my_table 中选择一个数据帧,进行一些转换,然后尝试写回原始 table。
我试过以下方法:
df.write.insertInto('table_name', overwrite='true')
。
这会引发以下错误:
pyspark.sql.utils.AnalysisException: Cannot insert overwrite into table that is also being read from.
df.write.mode('overwrite').parquet('my_path')
df.write.parquet('my_path', mode='overwrite')
df.write.save('my_path', format='parquet', mode = 'overwrite')
这些似乎都抛出了这个错误:
ERROR Client fs/client/fileclient/cc/client.cc:1802 Thread: 620 Open failed for file /my_path/part-r-00084-9, LookupFid error No such file or directory(2) 2016-04-26 16:47:17,0942 ERROR JniCommon fs/client/fileclient/cc/jni_MapRClient.cc:2488 Thread: 620 getBlockInfo failed, Could not open file /my_path/part-r-00084-9 16/04/26 16:47:17 WARN DAGScheduler: Creating new stage failed due to exception - job: 16
**请注意,如果文件格式是 orc,上面的方法 1 工作正常,但对于 parquet 会抛出该错误。
如有任何建议,我们将不胜感激!
从我目前发现的所有内容来看,读取和写入 parquet 格式文件的解决方案似乎是写入 temporary/staging 目录,删除原始目录,然后重命名临时目录到你原来的目录。 要在 pyspark 中执行此操作,您将需要以下命令:
import os
import shutil
shutil.rmtree('my_tmp_path')
os.rename('my_tmp_path', 'my_path)
为此你需要使用一个临时路径来写入。
问题是 Spark 主动使用实际路径读取数据,当您尝试写入同一个 parquet 文件时,它会生成错误。
Stella 已经给出了
在下面的代码中,我尝试使用临时文件保存数据框:
def write_dataframe(df, table_name):
# caches dataframe
df.cache()
dirout_tmp = PATH + table_name + "_tmp/"
dirout = PATH + table_name + "/"
# writing parquet file to a temporary location
df.write.parquet(dirout_tmp, mode='overwrite')
# removing original parquet
shutil.rmtree(dirout, ignore_errors=True)
# renaming the temp to the original path
os.rename(dirout_tmp, dirout)