未能在pyspark中覆盖镶木地板蜂巢表

时间:2016-04-27 20:43:58

标签: hive pyspark parquet

使用:spark 1.5.2,hive 1.2 我有一个镶木地板的外部蜂巢桌。我创建了一个.py脚本,从my_table中选择一个数据帧,进行一些转换,然后尝试写回原始表。

我尝试过以下方法:

  1. df.write.insertInto('table_name', overwrite='true')
  2. 这会引发以下错误:

      

    pyspark.sql.utils.AnalysisException:无法将覆盖插入到也从中读取的表中。

    1. df.write.mode('overwrite').parquet('my_path')
    2. df.write.parquet('my_path', mode='overwrite')
    3. df.write.save('my_path', format='parquet', mode = 'overwrite')
    4. 这些似乎都抛出了这个错误:

        

      错误客户端fs / client / fileclient / cc / client.cc:1802线程:620文件/ my_path / part-r-00084-9打开失败,LookupFid错误没有这样的文件或目录(2)           2016-04-26 16:47:17,0942错误JniCommon fs / client / fileclient / cc / jni_MapRClient.cc:2488线程:620 getBlockInfo失败,无法打开文件/ my_path / part-r-00084-9           16/04/26 16:47:17 WARN DAGScheduler:创建新阶段因异常而失败 - 工作:16

      **请注意,如果文件格式为orc,则上面的方法1可以正常工作,但会为镶木地板抛出该错误。

      任何建议都将不胜感激!

2 个答案:

答案 0 :(得分:1)

为此,您需要使用临时路径进行写入。

问题在于 Spark 正在主动使用实际路径来读取数据,并且当您尝试写入同一个 parquet 文件时,它会产生错误。

Stella 已经给出了应该做什么的hint,但是顺序不对。所以我决定给你一个更好更完整的答案,因为我必须自己解决:

在下面的代码中,我试图用临时文件保存数据帧:

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 :(得分:0)

从我迄今为止发现的所有内容中,读取和写回镶木地板文件的解决方案似乎是写入临时/暂存目录,删除原始目录,然后将临时目录重命名为你原来的。 要在pyspark中执行此操作,您需要以下命令:

import os
import shutil
shutil.rmtree('my_tmp_path')
os.rename('my_tmp_path', 'my_path)