【问题标题】:How to make a table that is automatically updated Hive如何制作一个自动更新 Hive 的表
【发布时间】: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 之间的阻抗不匹配。

标签: hive hdfs hiveql


【解决方案1】:

为了让 Hive 更新其表,我不得不求助于使用 Hive 的分区功能。通过在每次 Spark 运行期间创建一个新分区,我在 /hdfs/nodes 目录内部创建了一系列目录,如下所示:

/hdfs/nodes/timestamp=<a-timestamp>/<parquet-files>
/hdfs/nodes/timestamp=<a-different-timestamp>/<parquet-files>

然后,在每个 Spark 作业完成后,我在我的 Spark 作业中使用 HiveContext 运行 Hive 命令 MSCK REPAIR TABLE nodes,它会查找新分区并更新表。

我意识到这不是自动的,但它至少有效。

【讨论】:

    【解决方案2】:

    好的,所以您可能需要将文件封装在一个文件夹中。 Hive 外部表必须映射到可能有多个文件的文件夹上。

    尝试将文件写入:/path/to/hdfs/nodes/file 然后将外部表映射到/path/to/hdfs/nodes

    所以在文件夹节点中,您将只有 parquet 文件,它应该可以工作

    【讨论】:

    • 我更新了我的问题以表明我正在按照您的建议进行操作。我相信问题可能在于,由于我每次运行程序时都将多个文件写入该目录,Hive 可能只查看我第一次创建表时所在的文件。
    • 你能发布火花代码吗?我不明白为什么 hive 将部分数据搜索到节点目录中。
    • 已更新,但我相信我找到了解决方案,即使不是我的问题的真正答案。
    • 只是为了确定:该文件夹包含 Parquet 文件,没有其他内容(没有子目录,没有 SUCCESS__ 标志等)?并且所有 Parquet 文件都具有完全相同的结构,例如在显示的示例中,作业 1670f7a9-blahblah7251c663-blahblah 以相同的顺序映射了相同的列?
    猜你喜欢
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 2022-11-03
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    相关资源
    最近更新 更多