我将外部配置单元表存储为 Parquet,按列分区,as_of_dt
并通过火花流插入数据。现在每天都会添加新分区。我这样做是为了 msck repair table
让 hive 元存储获取新添加的分区信息。这是唯一的方法还是有更好的方法?我担心如果下游用户查询表,是否会msck repair
导致数据不可用或数据陈旧的问题?我正在浏览 HiveContext
API 并查看refreshTable
选项。知道这是否有意义refreshTable
吗?
2 回答
要直接回答您的问题 msck repair table,将检查表的分区是否处于活动状态。这意味着如果您删除了一些分区,并且不希望它们出现在表的 show partitions 命令中,msck repair table 应该删除它们。Msck 修复可能比 invalidate 或 refresh 语句花费更多时间,但是 Invalidate Metadata 仅在 Hive 内运行,仅更新 Hive Metastore。Refresh 仅在 Spark SQL 中运行并更新 Spark 元数据存储。
如果您在处理中的某处完成添加分区步骤,Hive 元存储应该没问题,但是如果您想通过 Spark SQL 访问配置单元表,您将需要通过 Spark(或 Impala 或其他更新 spark 的进程)更新元数据元数据)。
每当您更新或更改 hive 表的内容时,Spark Metastore 可能会不同步,导致您无法通过 spark.sql 命令集查询数据。这意味着如果您想查询需要保持 Spark 元存储同步的数据。
如果你有一个允许它的 Spark 版本,你应该刷新并将分区添加到 Spark 中的 Hive 表,以便所有元存储同步。以下是我的做法:
//Non-Partitioned Table
outputDF.write.format("parquet").mode("overwrite").load(fileLocation)
spark.sql("refresh table " + tableName)
//Partitioned Table
outputDF.write.format("parquet").mode("overwrite").load(fileLocation + "/" + partition)
val addPartitionsStatement = "alter table" + tableName = " add if not exists partition(partitionKey='" + partition + "') location '" + fileLocation + "/" + partition + "'"
spark.sql(addPartitionsStatement)
spark.sql("refresh table " + tableName)
看起来 refreshTable 确实刷新了缓存的元数据,而不影响 Hive 元数据。
医生说:
使给定表的所有缓存元数据失效并刷新。出于性能原因,Spark SQL 或其使用的外部数据源库可能会缓存有关表的某些元数据,例如块的位置。当那些在 Spark SQL 之外发生变化时,用户应该调用这个函数来使缓存失效。
方法不会更新 Hive 元数据,因此需要修复。