J'essaie de joindre efficacement deux DataFrames, dont l'un est volumineux et le second, un peu plus petit.
Y a-t-il un moyen d'éviter tout ce brassage? Je ne peux pas définir autoBroadCastJoinThreshold
, car il ne prend en charge que les entiers - et le tableau que je tente de diffuser est légèrement supérieur à un nombre entier d'octets.
Y a-t-il un moyen de forcer la diffusion en ignorant cette variable?
Dans SparkSQL, vous pouvez voir le type de jointure en cours en appelant queryExecution.executedPlan
. Comme avec le noyau Spark, si l’une des tables est beaucoup plus petite que l’autre, vous pouvez souhaiter une jointure de hachage de diffusion. Vous pouvez indiquer à Spark SQL qu'un DF donné doit être diffusé pour la jointure en appelant la méthode broadcast
sur le DataFrame
avant de le rejoindre
Exemple: largedataframe.join(broadcast(smalldataframe), "key")
en termes de DWH, où largedataframe peut ressembler à fait
smalldataframe peut ressembler à dimension
Comme décrit par mon livre préféré (HPS), les pls. voir ci-dessous pour avoir une meilleure compréhension ..
Remarque: ci-dessus, broadcast
provient de import org.Apache.spark.sql.functions.broadcast
Et non de SparkContext
.
Spark utilise également automatiquement le spark.sql.conf.autoBroadcastJoinThreshold
Pour déterminer si un tableau doit être diffusé.
def
explain(): Unit
Prints the physical plan to the console for debugging purposes.
Existe-t-il un moyen de forcer la diffusion en ignorant cette variable?
sqlContext.sql("SET spark.sql.autoBroadcastJoinThreshold = -1")
NOTE:
Une autre note similaire hors de la boîte w.r.t. Hive (not spark): Une chose similaire peut être obtenue en utilisant Hive hint
MAPJOIN
comme ci-dessous ...
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
Lectures supplémentaires: S'il vous plaît se référer mon article sur BHJ, SHJ, SMJ
Vous pouvez indiquer qu'un cadre de données doit être diffusé en utilisant left.join(broadcast(right), ...)
Réglage spark.sql.autoBroadcastJoinThreshold = -1
désactivera complètement la diffusion. Voir Autres options de configuration dans Spark Guide SQL, DataFrames and Datasets) .
C'est une limitation de courant d'étincelle, voir SPARK-6235 . La limite de 2 Go s'applique également aux variables de diffusion.
Etes-vous sûr qu’il n’ya pas d’autre moyen de le faire, par exemple partitionnement différent?
Sinon, vous pouvez y remédier en créant manuellement plusieurs variables de diffusion dont la valeur est inférieure à 2 Go.
J'ai trouvé ce code fonctionne pour Broadcast Join in Spark 2.11 version 2.0.0.
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()
Voici la référence pour le code ci-dessus Blog de Henning Kropp, Broadcast Join avec Spark