web-dev-qa-db-ja.com

DataFrame結合の最適化-ブロードキャストハッシュ結合

2つのDataFrameを効果的に結合しようとしています。1つは大きく、2つ目は少し小さくなっています。

このすべてのシャッフルを回避する方法はありますか? autoBroadCastJoinThresholdを設定することはできません。整数のみをサポートしているためです。また、ブロードキャストしようとしているテーブルは、整数のバイト数よりも少し大きいです。

この変数を無視してブロードキャストを強制する方法はありますか?

31
NNamed

ブロードキャストハッシュ結合(map side joinまたはMapreduceのマップ側結合に類似):

SparkSQLでは、_queryExecution.executedPlan_を呼び出すことにより、実行されている結合のタイプを確認できます。コアSparkと同様に、テーブルの1つが他のテーブルよりもはるかに小さい場合、ブロードキャストハッシュ結合が必要になる場合があります。 Spark SQLに、broadcastでメソッドDataFrameを呼び出すことで、指定されたDFを結合のためにブロードキャストするようにヒントを出すことができます。

例:largedataframe.join(broadcast(smalldataframe), "key")

dWH用語では、largedataframeはfact
smalldataframeはdimensionのようになります

私のお気に入りの本(HPS)plsで説明されているように。理解を深めるために、以下を参照してください。 enter image description here

注:上記のbroadcastSparkContextからではなく_import org.Apache.spark.sql.functions.broadcast_からのものです

また、Sparkは_spark.sql.conf.autoBroadcastJoinThreshold_を自動的に使用して、テーブルをブロードキャストする必要があるかどうかを判断します。

ヒント:DataFrame.explain()メソッドを参照してください

_def
explain(): Unit
Prints the physical plan to the console for debugging purposes.
_

この変数を無視してブロードキャストを強制する方法はありますか?

sqlContext.sql("SET spark.sql.autoBroadcastJoinThreshold = -1")


注:

別の同様のすぐに使えるノートw.r.t. Hive(スパークではありません):HiveヒントMAPJOINを使用すると、以下のような同様のことが実現できます...

_Select /*+ MAPJOIN(b) */ a.key, a.value from a join b on a.key = b.key

Hive> set Hive.auto.convert.join=true;
Hive> set Hive.auto.convert.join.noconditionaltask.size=20971520
Hive> set Hive.auto.convert.join.noconditionaltask=true;
Hive> set Hive.auto.convert.join.use.nonstaged=true;
Hive> set Hive.mapjoin.smalltable.filesize = 30000000; // default 25 mb made it as 30mb
_

さらに読む:私の BHJ、SHJ、SMJに関する記事 を参照してください

67
Ram Ghadiyaram

left.join(broadcast(right), ...)を使用して、データフレームがブロードキャストされるようにヒントを出すことができます

18
Sebastian Piu

設定spark.sql.autoBroadcastJoinThreshold = -1はブロードキャストを完全に無効にします。 Spark SQL、DataFrames and Datasets Guide のその他の設定オプション)を参照してください。

4
Vishal Gupta

これは現在のスパークの制限です。 SPARK-6235 を参照してください。 2GBの制限は、ブロードキャスト変数にも適用されます。

これを行う他の良い方法はありませんか?異なるパーティション?

それ以外の場合は、それぞれ<2GBである複数のブロードキャスト変数を手動で作成することにより、回避することができます。

3
dpeacock

このコードは、Spark 2.11バージョン2.0.0のBroadcast Joinで機能します。

import org.Apache.spark.sql.functions.broadcast  

val employeesDF = employeesRDD.toDF
val departmentsDF = departmentsRDD.toDF

// materializing the department data
val tmpDepartments = broadcast(departmentsDF.as("departments"))

import context.implicits._

employeesDF.join(broadcast(tmpDepartments), 
   $"depId" === $"id",  // join by employees.depID == departments.id 
   "inner").show()

上記のコードのリファレンスは次のとおりです Henning Kroppブログ、Sparkによるブロードキャスト参加

1
SparkleGoat