刷新外部Hive表 vs 使用MSCK修复表格

15

我有一个存储为Parquet格式的外部Hive表,按照一个名为as_of_dt的列进行分区,并通过Spark Streaming插入数据。现在每天都会添加新的分区。我正在执行msck repair table,以便Hive metastore获取新添加的分区信息。这是唯一的方法吗?还是有更好的方式?我担心下游用户查询表时,msck repair会导致数据不可用或过期数据的问题。我正在查看HiveContext API,并看到了refreshTable选项。你有什么想法,是否可以使用refreshTable代替?


你的Spark Streaming应用程序是否可以在创建新目录时简单地执行“ALTER TABLE ADD PARTITION”操作呢?我知道Spark对Hive SQL的支持有限,但有一些解决方法,例如使用WebHCat... - Samson Scharfrichter
流媒体应用程序使用 dataframe.write.mode("append").partitionBy(partitionKeys).parquet(baseDirectory)。Spark 内部会自动添加外部 Parquet 文件夹。只是想知道是否 msck repair 是唯一的选择。 - Ajith Kannan
2个回答

21

直接回答您的问题,msck repair table会检查一个表的分区是否处于激活状态。这意味着如果您删除了一些分区,并且不希望它们在show partitions命令中显示出来,msck repair table应该将其删除。与invalidate或refresh语句相比,msck repair可能需要更长时间,但是Invalidate Metadata仅在Hive中运行,只更新Hive Metastore。Refresh仅在Spark SQL中运行,并更新Spark元数据存储。

如果您在处理过程中完成了添加分区步骤,则Hive metastore应该没有问题,但是如果您想通过Spark SQL访问Hive表,则需要通过Spark(或Impala或其他更新Spark元数据的进程)更新元数据。

每当您更新或更改Hive表的内容时,Spark metastore都可能失去同步,导致您无法通过spark.sql命令集查询数据。这意味着如果您想查询该数据,则需要保持Spark metastore同步。

如果您具有允许的Spark版本,应在Spark中刷新和添加Hive表的分区,以便所有metastores保持同步。以下是我的做法:

//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)

2
非常感谢afeldman。目前,我有一个带有一些列和as_of_dt作为分区的表格。因此,每天都会添加新记录,并且由于分区值的更改,它将进入一个新的分区。我正在执行dataframe.write.mode("append").partitionBy(partitionKeys).parquet(baseDirectory),然后是MSCK REPAIR TABLE。那么,如果我使用alter table add if not exists partition和refresh table来代替msck repair,我会得到任何好处吗? - Ajith Kannan

5
看起来 refreshTable 确实可以刷新缓存的元数据,但不影响 Hive 元数据。 文档 表示:

使给定表的所有缓存的元数据失效并刷新。 出于性能原因,Spark SQL 或其使用的外部数据源库可能会缓存有关表的某些元数据,例如块的位置。当这些元数据在 Spark SQL 外部更改时,用户应调用此函数来使缓存无效。

该方法不更新 Hive 元数据,因此需要进行修复。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接