私は、Apache Spark HDFSを使用するクラスターで作業しています。私が理解している限り、HDFSはデータノードでファイルを配布しています。 、パーティションに分割されます。
rdd = SparkContext().textFile("hdfs://.../file.txt")
apache Sparkから。 rddは現在、ファイルシステム上の「file.txt」と同じパーティションを自動的に作成していますか?電話をかけるとどうなりますか
rdd.repartition(x)
ここで、x> hdfsが使用するパーティションはどこですか? Sparkはhdfsのデータを物理的に再配置してローカルで動作しますか?
例:30GBのテキストファイルをHDFSシステムに配置し、10個のノードに配布しています。 Spark a)同じ10パーティトンを使用しますか?およびb)repartition(1000)を呼び出したときにクラスター全体で30GBをシャッフルしますか?
SparkはHDFSからファイルを読み込むと、単一の入力分割に対して単一のパーティションを作成します。入力分割は、このファイルの読み込みに使用されるHadoop InputFormat
によって設定されます。たとえば、 textFile()
を使用すると、HadoopではTextInputFormat
になり、HDFSの単一ブロックに対して単一のパーティションが返されます(ただし、パーティション間の分割は行分割ではなく、行分割で行われます正確なブロック分割)、圧縮テキストファイルがない場合、圧縮ファイルの場合は、単一ファイルに対して単一パーティションを取得します(圧縮テキストファイルは分割できないため)。
rdd.repartition(x)
を呼び出すと、N
にあるrdd
パーティションから、必要なx
パーティションへのデータのシャッフルを実行します。ラウンドロビン方式で行われます。
HDFSに30GBの非圧縮テキストファイルが保存されている場合、デフォルトのHDFSブロックサイズ設定(128MB)で235ブロックに保存されます。つまり、このファイルから読み取るRDDには235パーティションがあります。 repartition(1000)
を呼び出すと、RDDはrepartitionedとマークされますが、実際には、このRDDの上でアクションを実行する場合にのみ1000パーティションにシャッフルされます(遅延実行の概念)
「HDFSのブロックをSparkパーティションとしてのワーカー)にロードする方法」のスナップショットを次に示します。
この画像では、4つのHDFSブロックがSpark 3つのワーカーメモリ内のパーティションとしてロードされます
例:30GBのテキストファイルをHDFSシステムに配置し、10個のノードに配布しています。
火花
a)同じ10個のパーティションを使用しますか?
Sparkは同じ10個のHDFSブロックをワーカーメモリにパーティションとしてロードします。 GBファイルのブロックサイズは3 GBでなければなりません 10パーティション/ブロックを取得するには(デフォルトの設定で)
b)repartition(1000)を呼び出したときにクラスター全体で30GBをシャッフルしますか?
はい、Spark=ワーカーメモリ内に1000個のパーティションを作成するために、ワーカーノード間でデータをシャッフルします。
注意:
HDFS Block -> Spark partition : One block can represent as One partition (by default)
Spark partition -> Workers : Many/One partitions can present in One workers
Spark-sqlでバケット化されていないHDFSファイル(パーケットなど)を読み取る場合、DataFrameパーティションの数_df.rdd.getNumPartitions
_は次の要因に依存します。
spark.default.parallelism
_(アプリケーションで使用可能な#coresに大まかに変換されます)spark.sql.files.maxPartitionBytes
_(デフォルト128MB)spark.sql.files.openCostInBytes
_(デフォルト4MB)パーティション数の概算は次のとおりです。
すべてのデータを並行して読み取るのに十分なコアがある場合(つまり、データの128MBごとに少なくとも1つのコア)
AveragePartitionSize ≈ min(4MB, TotalDataSize/#cores) NumberOfPartitions ≈ TotalDataSize/AveragePartitionSize
十分なコアがない場合、
_AveragePartitionSize ≈ 128MB NumberOfPartitions ≈ TotalDataSize/AveragePartitionSize
_
正確な計算はやや複雑で、FileSourceScanExecのコードベースで見つけることができます。 here を参照してください。
@ 0x0FFFへの追加HDFSから入力ファイルとして取得した場合、このrdd = SparkContext().textFile("hdfs://.../file.txt")
のように計算され、_rdd.getNumPatitions
_を実行するとMax(2, Number of HDFS block)
になります。私は多くの実験を行い、結果としてこれを見つけました。再度明示的にrdd = SparkContext().textFile("hdfs://.../file.txt", 400)
を実行してパーティションとして400を取得するか、_rdd.repartition
_で再パーティション化するか、rdd.coalesce(10)
で10に減らすこともできます。