web-dev-qa-db-ja.com

外部Hiveテーブルの更新テーブルとMSCKの修復

外部HiveテーブルはParquetとして保存され、列as_of_dtとデータはsparkストリーミング経由で挿入されます。現在、毎日新しいパーティションが追加されています。私はmsck repair tableこれにより、Hiveメタストアは新しく追加されたパーティション情報を取得します。これが唯一の方法ですか、それともより良い方法がありますか?テーブルを照会するダウンストリームユーザーがmsck repairデータまたは古いデータの非可用性に問題がありますか?私はHiveContext AP​​Iを使用していましたが、refreshTableオプションを参照してください。代わりにrefreshTableを使用するのが理にかなっているなら、どんな考えですか?

6
Ajith Kannan

質問msck repair tableに直接回答するには、テーブルのパーティションがアクティブかどうかを確認します。少数のパーティションを削除し、テーブルのshow partitionsコマンド内に表示したくない場合、msck repair tableはそれらを削除する必要があります。 Msckの修復は、無効化ステートメントまたは更新ステートメントよりも時間がかかりますが、メタデータの無効化は、Hive Metastoreのみを更新するHive内でのみ実行されます。更新はSpark SQLでのみ実行され、Sparkメタデータストアを更新します。

Hiveメタストアは、処理のどこかでパーティションの追加ステップを完了する場合は問題ありませんが、Spark SQLを介してHiveテーブルにアクセスする場合は、Sparkを介してメタデータを更新する必要があります(またはImpalaまたはsparkメタデータを更新する別のプロセス)。

Hiveテーブルのコンテンツを更新または変更すると、Sparkメタストアが同期しなくなる可能性があり、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)
9
afeldman

RefreshTableはキャッシュされたメタデータを更新するように見えますが、Hiveメタデータには影響しません。

Doc 言います:

指定されたテーブルのキャッシュされたすべてのメタデータを無効にして更新します。パフォーマンス上の理由から、Spark SQLまたは使用する外部データソースライブラリは、ブロックの場所など、テーブルに関する特定のメタデータをキャッシュする場合があります。これらがSpark SQL、ユーザーはこの関数を呼び出してキャッシュを無効にする必要があります。

メソッドはHiveメタデータを更新しないため、修復が必要です。

1
leftjoin