Spark=寄木細工のファイルの分割キーを知っていて、シャッフルを避けるためにこの情報を使用するかどうかを知りたいです。
コンテキスト:
実行中Spark 2.0.1ローカルSparkSessionを実行しています。ディスク上に寄木細工ファイルとして保存しているcsvデータセットがあります。
val df0 = spark
.read
.format("csv")
.option("header", true)
.option("delimiter", ";")
.option("inferSchema", false)
.load("SomeFile.csv"))
val df = df0.repartition(partitionExprs = col("numerocarte"), numPartitions = 42)
df.write
.mode(SaveMode.Overwrite)
.format("parquet")
.option("inferSchema", false)
.save("SomeFile.parquet")
列numerocarte
で42個のパーティションを作成しています。これにより、複数のnumerocarte
を同じパーティションにグループ化する必要があります。 write
時にpartitionBy( "numerocarte")を実行したくないのは、カードごとに1つのパーティションが必要ないためです。それは何百万人になります。
その後、別のスクリプトでこれを読みましたSomeFile.parquet
ファイルを寄せ集め、その上でいくつかの操作を行います。特に、window function
その上で、寄木細工のファイルが再分割されたのと同じ列で分割が行われます。
import org.Apache.spark.sql.expressions.Window
import org.Apache.spark.sql.functions._
val df2 = spark.read
.format("parquet")
.option("header", true)
.option("inferSchema", false)
.load("SomeFile.parquet")
val w = Window.partitionBy(col("numerocarte"))
.orderBy(col("SomeColumn"))
df2.withColumn("NewColumnName",
sum(col("dollars").over(w))
read
の後、repartition
が期待どおりに機能し、DataFrame df2
には42個のパーティションがあり、それぞれに異なるカードがあります。
質問:
df2
は列numerocarte
?でパーティション分割されていますか?DataFrame
のパーティションキーを確認するにはどうすればよいですか?これのためのコマンドはありますか?パーティションの数を確認する方法は知っていますが、パーティションキーを確認する方法はありますか?read
の後に42パーティション、withColumn
の後に200パーティションになり、SparkがDataFrame
。Sparkは、データフレームdf2が列numerocarteでパーティション分割されていることを知っていますか?
ありません。
わからない場合は、Sparkが正しい列でデータが既にパーティション分割されていることをどのように伝えますか?
あなたはしません。シャッフルされたデータを保存したからといって、同じ分割でロードされることを意味するわけではありません。
DataFrameのパーティションキーを確認するにはどうすればよいですか?
データを読み込んだ後はパーティションキーはありませんが、queryExecution
のPartitioner
を確認できます。
実際には:
partitionBy
のDataFrameWriter
メソッドを使用します。bucketBy
を使用します。詳細な例については、 DataFrameのパーティション分割の定義方法 を参照してください。
今後の参考のために、自分の質問に答えています。
@ user8371915の提案に従って、bucketByは機能します!
DataFrame df
を保存しています:
df.write
.bucketBy(250, "userid")
.saveAsTable("myNewTable")
次に、このテーブルをロードする必要がある場合:
val df2 = spark.sql("SELECT * FROM myNewTable")
val w = Window.partitionBy("userid")
val df3 = df2.withColumn("newColumnName", sum(col("someColumn")).over(w)
df3.explain
私は確認しますuserid
でパーティション分割されたdf2
でウィンドウ関数を実行するとシャッフルはありません!ありがとう@ user8371915!
調査中に学んだこと
spark.read.format("parquet").load("path/to/myNewTable")
で読むことができますが、この方法で作成されたDataFrame
は元のパーティションを保持しません!正しくパーティション化されたselect
を取得するには、spark.sql
DataFrame
を使用する必要があります。spark.sql("describe formatted myNewTable").collect.foreach(println)
を使用してテーブル内を見ることができます。これにより、バケットに使用された列とバケットの数がわかります。.sortBy()
を使用して、書き込み時にバケット内のデータを並べ替えることができ、並べ替えはHiveテーブルにも保存されます。 df.write.bucketBy(250, "userid").sortBy("somColumnName").saveAsTable("myNewTable")
myNewTable
はローカルScala SBTプロジェクトのspark-warehouse
フォルダーに保存されます。spark-submit
を介してmesosを使用してクラスターモードで保存する場合、私にとっては、/user/Hive/warehouse
にありました。spark-submit
を実行する場合、SparkSession
に2つのオプションを追加する必要があります:.config("Hive.metastore.uris", "thrift://addres-to-your-master:9083")
と.enableHiveSupport()
。そうしないと、作成したHiveテーブルは表示されません。spark.sql("USE your database")
を実行します。2018年5月2日更新
sparkバケットとHiveテーブルの作成で問題が発生しました。 理由はSpark saveAsTable with bucketBy何千ものファイルを作成しますか?