web-dev-qa-db-fra.com

Pourquoi la jointure échoue-t-elle avec "Java.util.concurrent.TimeoutException: Futures expirés après [300 secondes]"?

J'utilise Spark 1.5.

J'ai deux dataframes de la forme:

scala> libriFirstTable50Plus3DF
res1: org.Apache.spark.sql.DataFrame = [basket_id: string, family_id: int]

scala> linkPersonItemLessThan500DF
res2: org.Apache.spark.sql.DataFrame = [person_id: int, family_id: int]

libriFirstTable50Plus3DF A 766 151 enregistrements tandis que linkPersonItemLessThan500DF A 26 694 353 enregistrements. Notez que j’utilise repartition(number) sur linkPersonItemLessThan500DF Car j’ai l’intention de les rejoindre plus tard. Je suis le code ci-dessus avec:

val userTripletRankDF = linkPersonItemLessThan500DF
     .join(libriFirstTable50Plus3DF, Seq("family_id"))
     .take(20)
     .foreach(println(_))

pour lequel je reçois cette sortie:

16/12/13 15:07:10 INFO scheduler.TaskSetManager: Finished task 172.0 in stage 3.0 (TID 473) in 520 ms on mlhdd01.mondadori.it (199/200)
Java.util.concurrent.TimeoutException: Futures timed out after [300 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:107)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:        at scala.concurrent.Await$.result(package.scala:107)
at org.Apache.spark.sql.execution.joins.BroadcastHashJoin.doExecute(BroadcastHashJoin.scala:110)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:140)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:138)
at org.Apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:147)
at org.Apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:138)
at org.Apache.spark.sql.execution.TungstenProject.doExecute(basicOperators.scala:86)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:140)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:138)
at org.Apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:147)
at org.Apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:138)
at org.Apache.spark.sql.execution.ConvertToSafe.doExecute(rowFormatConverters.scala:63)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:140)
at org.Apache.spark.sql.execution.SparkPlan$$anonfun$execute$5.apply(SparkPlan.scala:138)
at org.Apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:147)
 at org.Apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:138)
 at org.Apache.spark.sql.execution.SparkPlan.executeTake(SparkPlan.scala:190)
 at org.Apache.spark.sql.execution.Limit.executeCollect(basicOperators.scala:207)
 at org.Apache.spark.sql.DataFrame$$anonfun$collect$1.apply(DataFrame.scala:1386)
 at org.Apache.spark.sql.DataFrame$$anonfun$collect$1.apply(DataFrame.scala:1386)
 at org.Apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:56)
 at org.Apache.spark.sql.DataFrame.withNewExecutionId(DataFrame.scala:1904)
 at org.Apache.spark.sql.DataFrame.collect(DataFrame.scala:1385)
 at org.Apache.spark.sql.DataFrame.head(DataFrame.scala:1315)
 at org.Apache.spark.sql.DataFrame.take(DataFrame.scala:1378)
 at org.Apache.spark.sql.DataFrame.showString(DataFrame.scala:178)
 at org.Apache.spark.sql.DataFrame.show(DataFrame.scala:402)
 at org.Apache.spark.sql.DataFrame.show(DataFrame.scala:363)
 at org.Apache.spark.sql.DataFrame.show(DataFrame.scala:371)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:72)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:77)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:79)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:81)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:83)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:85)
 at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:87)
 at $iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:89)
 at $iwC$$iwC$$iwC$$iwC.<init>(<console>:91)
 at $iwC$$iwC$$iwC.<init>(<console>:93)
 at $iwC$$iwC.<init>(<console>:95)
 at $iwC.<init>(<console>:97)
 at <init>(<console>:99)
 at .<init>(<console>:103)
 at .<clinit>(<console>)
 at .<init>(<console>:7)
 at .<clinit>(<console>)
 at $print(<console>)
 at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
 at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
 at Java.lang.reflect.Method.invoke(Method.Java:606)
 at org.Apache.spark.repl.SparkIMain$ReadEvalPrint.call(SparkIMain.scala:1065)
 at org.Apache.spark.repl.SparkIMain$Request.loadAndRun(SparkIMain.scala:1340)
 at org.Apache.spark.repl.SparkIMain.loadAndRunReq$1(SparkIMain.scala:840)
 at org.Apache.spark.repl.SparkIMain.interpret(SparkIMain.scala:871)
 at org.Apache.spark.repl.SparkIMain.interpret(SparkIMain.scala:819)
 at org.Apache.spark.repl.SparkILoop.reallyInterpret$1(SparkILoop.scala:857)
 at org.Apache.spark.repl.SparkILoop.interpretStartingWith(SparkILoop.scala:902)
 at org.Apache.spark.repl.SparkILoop.command(SparkILoop.scala:814)
 at org.Apache.spark.repl.SparkILoop.processLine$1(SparkILoop.scala:657)
 at org.Apache.spark.repl.SparkILoop.innerLoop$1(SparkILoop.scala:665)
 at org.Apache.spark.repl.SparkILoop.org$Apache$spark$repl$SparkILoop$$loop(SparkILoop.scala:670)
 at org.Apache.spark.repl.SparkILoop$$anonfun$org$Apache$spark$repl$SparkILoop$$process$1.apply$mcZ$sp(SparkILoop.scala:997)
 at org.Apache.spark.repl.SparkILoop$$anonfun$org$Apache$spark$repl$SparkILoop$$process$1.apply(SparkILoop.scala:945)
 at org.Apache.spark.repl.SparkILoop$$anonfun$org$Apache$spark$repl$SparkILoop$$process$1.apply(SparkILoop.scala:945)
 at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
 at org.Apache.spark.repl.SparkILoop.org$Apache$spark$repl$SparkILoop$$process(SparkILoop.scala:945)
 at org.Apache.spark.repl.SparkILoop.process(SparkILoop.scala:1059)
 at org.Apache.spark.repl.Main$.main(Main.scala:31)
 at org.Apache.spark.repl.Main.main(Main.scala)
 at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
 at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
 at Java.lang.reflect.Method.invoke(Method.Java:606)
 at org.Apache.spark.deploy.SparkSubmit$.org$Apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:672)
 at org.Apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:180)
 at org.Apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:205)
 at org.Apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:120)
 at org.Apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

et je ne comprends pas quel est le problème. Est-ce aussi simple que d'augmenter le temps d'attente? La jointure est-elle trop intensive? Ai-je besoin de plus de mémoire? Le shufffling est-il intensif? Quelqu'un peut-il aider?

40

Cela est dû au fait que Spark tente de joindre le hachage en diffusion et que l’un des DataFrames est très volumineux; son envoi prend donc beaucoup de temps.

Vous pouvez:

  1. Réglez plus haut spark.sql.broadcastTimeout Pour augmenter le délai d'attente - spark.conf.set("spark.sql.broadcastTimeout", newValueForExample36000)
  2. persist() les deux DataFrames, puis Spark utilisera Shuffle Join - reference from here

PySpark

Dans PySpark, vous pouvez définir la configuration lorsque vous créez le contexte spark de la manière suivante:

spark = SparkSession
  .builder
  .appName("Your App")
  .config("spark.sql.broadcastTimeout", "36000")
  .getOrCreate()
61
T. Gawęda

Juste pour ajouter un peu de contexte de code à réponse très concise de @T. Gawęda .


Dans votre application Spark, Spark, SQL a choisi une diffusion par hachage de diffusion pour la jointure car "libriFirstTable50Plus3DF a 766 151 enregistrements" qui se trouvait être inférieure au seuil de diffusion dit (par défaut à 10Mo).

Vous pouvez contrôler le seuil de diffusion à l'aide de la propriété de configuration spark.sql.autoBroadcastJoinThreshold .

spark.sql.autoBroadcastJoinThreshold Configure la taille maximale en octets d'une table qui sera diffusée à tous les nœuds de travail lors de la réalisation d'une jointure. En définissant cette valeur sur -1, la diffusion peut être désactivée. Notez que les statistiques ne sont actuellement prises en charge que pour les tables Hive Metastore où la commande ANALYZE TABLE COMPUTE STATISTICS noscan a été exécutée.

Vous pouvez trouver ce type de jointure dans la trace de la pile:

org.Apache.spark.sql.execution.joins.BroadcastHashJoin.doExecute (BroadcastHashJoin.scala: 110)

BroadcastHashJoin opérateur physique dans Spark) SQL utilise une variable de diffusion pour distribuer le plus petit jeu de données à Spark (plutôt que d’en envoyer une copie avec chaque tâche).

Si vous utilisiez explain pour examiner le plan de requête physique, vous remarquerez que la requête utilise l'opérateur BroadcastExchangeExec . C’est ici que vous pouvez voir machines sous-jacentes à la diffusion du plus petit tablea (et délai d’expiration).

override protected[sql] def doExecuteBroadcast[T](): broadcast.Broadcast[T] = {
  ThreadUtils.awaitResult(relationFuture, timeout).asInstanceOf[broadcast.Broadcast[T]]
}

doExecuteBroadcast fait partie de SparkPlan du contrat que chaque opérateur physique Spark suit SQL qui permet la diffusion si nécessaire. BroadcastExchangeExec en a besoin par hasard .

Le paramètre timeout est ce que vous recherchez.

private val timeout: Duration = {
  val timeoutValue = sqlContext.conf.broadcastTimeout
  if (timeoutValue < 0) {
    Duration.Inf
  } else {
    timeoutValue.seconds
  }
}

Comme vous pouvez le constater, vous pouvez la désactiver complètement (en utilisant une valeur négative), ce qui impliquerait d'attendre que la variable broadcast soit envoyée indéfiniment aux exécuteurs ou d'utiliser sqlContext.conf.broadcastTimeout qui est exactement spark.sql.broadcastTimeout propriété de configuration. La valeur par défaut est 5 * 60 secondes que vous pouvez voir dans le stacktrace:

Java.util.concurrent.TimeoutException: les contrats à terme ont expiré après [300 secondes]

21
Jacek Laskowski

Dans mon cas, cela était dû à une diffusion sur une grande base de données:

df.join(broadcast(largeDF))

Donc, sur la base des réponses précédentes, je l'ai corrigé en supprimant la diffusion:

df.join(largeDF)
0
Pedro H

En plus d'augmenter spark.sql.broadcastTimeout ou persist () les deux DataFrames,

Vous pouvez essayer:

1.disable broadcast en définissant spark.sql.autoBroadcastJoinThreshold à -1

2.increase the spark mémoire du pilote en définissant spark.driver.memory à une valeur supérieure.

0
lasclocker