【发布时间】:2015-08-26 19:48:57
【问题描述】:
我在 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。但是,这对我来说不是这样,我不知道发生了什么。
我再次将相同的数据插入数据库,并查询表。它包含与以前相同数量的数据。然后,我创建了一个具有不同名称的相同表。它包含两倍的数据,这是正确的数量。
问题可能与元存储数据库有关。我使用 PostgreSQL 而不是 Derby 作为数据库。
相关信息:
- Hive 0.13.0
- Spark 流式传输 1.4.1
- PostgreSQL 9.3
- CentOS 7
编辑:
检查 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 时导致 Hive 出错的文件。这意味着外部表不是动态的,接受目录中的任何文件(如果你在 HDFS 中这样称呼它),而是可能只是在创建时跟踪目录中的 parquet 文件列表。
示例 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”
查看我关于获取Hive external tables to detect new files.的其他问题
【问题讨论】:
-
如果删除表然后重新创建它,会发生什么情况?
-
我做了一个`select count(*) from nodes;',删除了表,重新创建了表,然后重新进行了查询。两次结果相同。
-
您声明“没有显示新数据”——就像 Spark 作业仍在写入文件一样,它们的长度小于 1 个块,因此 HDFS 不会使它们可用于其他进程,例如蜂巢。然后你提到一个 IOError File doesn't exist - 就像 Hive 在设置执行计划时检测到文件,然后一些进程在实际执行之前删除了文件(小型 Parquet 文件的后台合并进程?! 我不熟悉这种格式,但这是 ORC 处理“交易”的方式)。
-
所以不清楚到底发生了什么,但闻起来像是 Spark、HDFS 和 Hive 之间的阻抗不匹配。