web-dev-qa-db-ja.com

DatabricksでPySparkを使用したAzure DataLakeのpartitionBy&上書き戦略

Azure環境に単純なETLプロセスがあります

blob storage> datafactory> datalake raw> databricks> datalake curated> datwarehouse(main ETL)。

このプロジェクトのデータセットはそれほど大きくありません(最大100万行、20列のギブまたはテイク)。ただし、データレイクでParquetファイルとして適切にパーティション分割しておく必要があります。

現在私はいくつかの単純なロジックを実行して、私のファイルをビジネスカレンダーに基づいて湖のどこに配置すべきかを判断しています。

ファイルは漠然とこのように見えます

_Year Week Data
2019 01   XXX
2019 02   XXX
_

次に、特定のファイルを次の形式にパーティション分割して、存在するデータを置き換え、新しいデータ用の新しいフォルダーを作成します。

_curated ---
           dataset --
                     Year 2019 
                              - Week 01 - file.pq + metadata
                              - Week 02 - file.pq + metadata
                              - Week 03 - file.pq + datadata #(pre existing file)
_

メタデータはsuccessおよびcommitsであり、自動生成されます。

このため、Pyspark 2.4.3では次のクエリを使用します。

_dataset.repartition(1).write.mode('overwrite')\
                         .partitionBy('Year','Week').parquet('\curataed\dataset')
_

このコマンドを単独で使用すると、ターゲットパーティション内の既存のデータが上書きされます

したがって、_Week 03_は失われます。

spark.conf.set("spark.sql.sources.partitionOverwriteMode","dynamic")を使用すると問題が停止し、ターゲットファイルのみが上書きされるようですが、これがデータレイク内のファイルを処理するための最良の方法であるかどうか疑問に思いますか?

また、上記の機能に関するドキュメントを見つけるのが難しいと感じました。

私の最初の本能は、単一の寄木細工をループして、各パーティションを手動で書き込むことでした。これにより、ファイルの名前付けとターゲットのパーティション分割をより詳細に制御できますが、それはすべての目的と目的のためであり、非常に遅くなります(そしてpandasマインドセット)

私の次の考えは、各パーティションを_/tmp_フォルダーに書き込み、各寄木細工のファイルを移動してから、必要に応じてファイルを置き換える/ファイルを作成することです。次に、何らかのメタデータログを作成しながら、_/tmp_フォルダーを削除します。

これにより良い方法/方法はありますか?

どんなガイダンスもいただければ幸いです。

ここでの最終目標は、すべての「キュレートされた」データ用のクリーンで安全な領域を確保し、さらにDataWarehouseに読み込んでさらにETLを行えるように寄木細工のファイルのログを保持することです。

5
Manakin

あなたのアプローチで重要な何かを見逃したが、既存のデータの上に新しいデータを書きたいと思われる場合は修正してください。

_write.mode('append')
_

_'overwrite'_の代わりに

データをバッチで分けて保持し、データウェアハウスへのアップロードまたは監査のために選択できるようにする場合、この情報をデータセットに含め、保存中に分割する以外に、適切な方法はありません。

_dataset.write.mode('append')\
                     .partitionBy('Year','Week', 'BatchTimeStamp').parquet('curated\dataset')
_

寄木細工のファイル形式への他の手動による介入は、パイプラインの信頼性を低下させたり、データを破壊したりする最悪のリスクで、せいぜいハックです。

Mohammadが言及しているDelta Lakeは、データレイクにデータを確実に格納するための総合的な良い提案であり、現在、黄金の業界標準です。特定のユースケースでは、履歴クエリを作成する機能を使用できます(すべてを追加してから、現在のデータセットと前のバッチの後の違いをクエリします)。ただし、監査ログは、デルタレイクの構成方法に限定されており、最短で7日なので、長期にわたって完全な情報が必要な場合は、とにかくバッチ情報を保存するというアプローチに従う必要があります。

より戦略的なレベルでは、生->キュレート-> DWをフォローするときに、別の「ホップ」を追加して、準備済みデータを「前処理済み」フォルダーに入れ、バッチで整理し、キュレートされたセットとDWセットの両方に追加することもできます。 。

副注として、.repartition(1)は寄木細工を使用する場合はあまり意味がありません。寄木細工はマルチファイル形式であるため、これを行うことによる唯一の影響はパフォーマンスへの悪影響です。ただし、使用している特定の理由がある場合はお知らせください。

1
Daniel

テーブルを直接書き込む代わりに、saveAsTableを追加で使用して、その前にパーティションを削除できます。

dataset.repartition(1).write.mode('append')\
                     .partitionBy('Year','Week').saveAsTable("tablename")

以前のパーティションを削除するため

partitions = [ (x["Year"], x["Week"]) for x in dataset.select("Year", "Week").distinct().collect()]
for year, week in partitions:
    spark.sql('ALTER TABLE tablename DROP IF EXISTS PARTITION (Year = "'+year+'",Week = "'+week+'")')
1
Anshuman