我在Hive中创建了一个外部表,它使用来自HDFS中Parquet商店的数据。
删除HDFS中的数据时,表中没有数据。当数据再次插入HDFS中的同一位置时,表格不会更新以包含新数据。如果我将新记录插入到包含数据的现有表中,则在运行Hive查询时不会显示新数据。
我如何在Hive中创建表:
CREATE EXTERNAL TABLE nodes (id string) STORED AS PARQUET LOCATION "/hdfs/nodes";
相关错误:
Error: java.io.FileNotFoundException: File does not exist: /hdfs/nodes/part-r-00038-2149d17d-f890-48bc-a9dd-5ea07b0ec590.gz.parquet
我看过几篇帖子说明外部表格中应包含最新数据,例如here。但是,对我来说情况并非如此,我也不知道发生了什么。
我再次将相同的数据插入数据库,并查询该表。它包含与以前相同数量的数据。然后我创建了一个具有不同名称的相同表。它的数据量是其中的两倍,这是合适的数量。
问题可能在于Metastore数据库。我使用PostgreSQL而不是Derby作为数据库。
相关信息:
编辑:
检查Parquet文件后,我发现部件文件看起来似乎是不兼容的文件名。
-rw-r--r-- 3 hdfs hdfs 18702811 2015-08-27 08:22 /hdfs/nodes/part-r-00000-1670f7a9-9d7c-4206-84b5-e812d1d8fd9a.gz.parquet
-rw-r--r-- 3 hdfs hdfs 18703029 2015-08-26 15:43 /hdfs/nodes/part-r-00000-7251c663-f76e-4903-8c5d-e0c6f61e0192.gz.parquet
-rw-r--r-- 3 hdfs hdfs 18724320 2015-08-27 08:22 /hdfs/nodes/part-r-00001-1670f7a9-9d7c-4206-84b5-e812d1d8fd9a.gz.parquet
-rw-r--r-- 3 hdfs hdfs 18723575 2015-08-26 15:43 /hdfs/nodes/part-r-00001-7251c663-f76e-4903-8c5d-e0c6f61e0192.gz.parquet
这些文件是导致Hive在上述错误中无法找到错误的文件。这意味着外部表不是动态的,接受目录中的任何文件(如果你在HDFS中调用它),而是可能只是在创建目录时跟踪目录中的镶木地板文件列表。
示例Spark代码:
nodes.foreachRDD(rdd => {
if (!rdd.isEmpty())
sqlContext.createDataFrame(rdd.map(
n => Row(n.stuff), ParquetStore.nodeSchema)
.write.mode(SaveMode.Append).parquet(node_name)
})
nodeSchema
是架构,node_name
是" / hdfs / nodes"
答案 0 :(得分:1)
为了让Hive更新其表,我不得不求助于使用Hive的分区功能。通过在每次Spark运行期间创建一个新分区,我在/hdfs/nodes
目录内部创建了一系列目录,如下所示:
/hdfs/nodes/timestamp=<a-timestamp>/<parquet-files>
/hdfs/nodes/timestamp=<a-different-timestamp>/<parquet-files>
然后,在每个Spark作业完成后,我在我的Spark作业中使用MSCK REPAIR TABLE nodes
运行Hive命令HiveContext
,它找到新的分区并更新表。
我意识到这不是自动的,但它至少有效。
答案 1 :(得分:0)
好的,你可能需要将文件封装在一个文件夹中。 Hive外部表必须映射到可能有多个文件的文件夹。
尝试将文件写入:/ path / to / hdfs / nodes / file 然后将外部表映射到/ path / to / hdfs / nodes
所以在文件夹节点中你只有镶木地板文件,它应该有效