DataFrame repartition()
メソッドとDataFrameWriter partitionBy()
メソッドの違いは何ですか?
両方が「データフレーム列に基づくパーティションデータ」に使用されることを望みますか?それとも違いはありますか?
repartition(COL)
を実行すると、計算中にパーティションが変更されます-spark.sql.shuffle.partitions
(デフォルト:200)パーティションを取得します。次に.write
を呼び出すと、多くのファイルを含む1つのディレクトリが取得されます。
.write.partitionBy(COL)
を実行すると、結果として、COLの一意の値と同じ数のディレクトリが取得されます。これにより、データの読み取りがさらに高速化され(列をパーティション分割することでフィルタリングする場合)、ストレージのスペースを節約できます(パーティション化列がデータファイルから削除されます)。
UPDATE:@conradleeの答えを参照してください。彼は、さまざまな方法を適用した後にディレクトリ構造がどのように見えるかだけでなく、両方のシナリオで得られるファイルの数も詳細に説明します。
気をつけて:受け入れられた答えはまったく正しくないと思います!これらの同様の名前の関数の振る舞いは、公式のspark文書で十分に文書化されていない重要かつ予想外の方法で異なるため、この質問を聞いてうれしいです。
受け入れられた答えの最初の部分は正しいです。df.repartition(COL, numPartitions=k)
を呼び出すと、ハッシュベースのパーティショナーを使用して、k
パーティションでデータフレームが作成されます。 COL
は、ここでパーティション化キーを定義します。単一の列または列のリストを指定できます。ハッシュベースのパーティショナーは、各入力行のパーティションキーを取得し、partition = hash(partitionKey) % k
などの方法でk
パーティションのスペースにハッシュします。これにより、同じパーティションキーを持つすべての行が同じパーティションに配置されることが保証されます。ただし、-複数のパーティションキーからの行が同じパーティションに存在することもあります(パーティションキー間のハッシュ衝突が発生した場合)および一部のパーティションが空の場合があります。
要約すると、df.repartition(COL, numPartitions=k)
の直感的でない側面は
k
パーティションは空かもしれませんが、他のパーティションには複数のパーティションキーの行が含まれているかもしれませんdf.write.partitionBy
の動作はまったく異なり、多くのユーザーが予期しない方法です。出力ファイルを日付パーティションに分割し、データが7日間にわたっているとします。また、df
には最初に10個のパーティションがあると仮定します。 df.write.partitionBy('day')
を実行すると、いくつの出力ファイルが必要になりますか?答えは「依存する」です。 df
の開始パーティションの各パーティションに毎日のデータが含まれている場合、答えは70です。df
の開始パーティションのそれぞれに正確に1日のデータが含まれている場合、答えは10です。
この動作をどのように説明できますか? df.write
を実行すると、df
の元のパーティションはそれぞれ個別に書き込まれます。つまり、元の10個のパーティションのそれぞれが「day」列で個別にサブパーティションに分割され、各サブパーティションに個別のファイルが書き込まれます。
この動作はかなり面倒で、データフレームを書き込むときにグローバルなパーティション分割を行う方法があればいいのにと思います。