Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 作为参数传递的广播值中的空指针_Apache Spark_Apache Spark Sql - Fatal编程技术网

Apache spark 作为参数传递的广播值中的空指针

Apache spark 作为参数传递的广播值中的空指针,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,:) 我想说我是Spark的新手,因为很多帖子都是从这里开始的……但事实上我并不是那么新。 尽管如此,我仍然面临广播变量的问题 当一个变量被广播时,每个执行器都会收到它的一个副本。稍后,当这个变量在执行器中执行的代码部分被引用时(比如map或foreach),如果驱动程序中设置的变量引用没有传递给它,那么执行器不知道我们在说什么。我认为这是最好的解释 我的问题是我得到了一个nullPointerException,即使我把广播引用传递给了执行者 class A { var broadca

:)

我想说我是Spark的新手,因为很多帖子都是从这里开始的……但事实上我并不是那么新。 尽管如此,我仍然面临广播变量的问题

当一个变量被广播时,每个执行器都会收到它的一个副本。稍后,当这个变量在执行器中执行的代码部分被引用时(比如map或foreach),如果驱动程序中设置的变量引用没有传递给它,那么执行器不知道我们在说什么。我认为这是最好的解释

我的问题是我得到了一个nullPointerException,即使我把广播引用传递给了执行者

class A {
    var broadcastVal: Broadcast[Dataframe] = _
    ...

    def method1 {
        broadcastVal = otherMethodWhichSendBroadcast
        doSomething(broadcastVal, others)
    }
}

class B {
    def doSomething(...) {
        forEachPartition {x => doSomethingElse(x, broadcasVal)}
    }
}

object C {
    def doSomethingElse(...) {
        broadcastVal.value.show --> Exception
    }
}
我错过了什么

提前谢谢

RDD和数据帧已经是分布式结构,不需要将它们作为局部变量广播。(
org.apache.spark.sql.functions.broadcast()
函数(在执行联接时使用)不是局部变量广播)


即使您尝试代码语法,它也不会显示任何编译错误,而是会抛出
RuntimeException
NullPointerException
一样100%有效。

解释该行为的示例:

package examples

import org.apache.log4j.Level
import org.apache.spark.broadcast.Broadcast
import org.apache.spark.sql.{DataFrame, SparkSession}

object BroadCastCheck extends App {
  org.apache.log4j.Logger.getLogger("org").setLevel(Level.OFF)
  val spark = SparkSession.builder().appName(getClass.getName).master("local").getOrCreate()
  val sc = spark.sparkContext
  val df = spark.range(100).toDF()
  var broadcastVal: Broadcast[DataFrame] = sc.broadcast(df)


  val t1 = sc.parallelize(0 until 10)
  val t2 = sc.broadcast(2) // this is right since its local variable can be primitive or map or any scala collection
  val t3 = t1.filter(_ % t2.value == 0).persist() //this is the way of ha
  t3.foreach {
    x =>
      println(x)
      // broadcastVal.value.toDF().show // null pointer  wrong way
    //   spark.range(100).toDF().show // null pointer  wrong way

  }
}

结果:(如果在上述代码中取消注释
broadcastVal.value.toDF().show
spark.range(100.toDF().show


进一步

感谢您这么快的回答!我现在明白了,完全有道理#facePalmEmoji我之所以尝试广播DF是因为我希望每个执行者都将其(全部)存储在内存中,从而避免询问驱动程序或其他执行者。它是一个流式应用程序,延迟非常重要。但我认为最好收集df,因为它很小,并作为MapObject进行广播。你认为有更好的方法吗?如果它的数据帧很小,记录数很少,那么就可以
收集
并作为局部变量进行广播。另一方面,您将获得内存不足异常。由于collect会将整个数据移动到驱动程序。。。还有一些基于需求的其他技术。一种方法是缓存
df。缓存将缓存在内存中。您可以在缓存的数据帧上使用连接(使用largedf.join(广播(smalldf)、Seq(匹配连接的键))来查找数据。它在spark core和spark streaming中工作。
Caused by: java.lang.NullPointerException
    at org.apache.spark.sql.execution.SparkPlan.sparkContext(SparkPlan.scala:56)
    at org.apache.spark.sql.execution.WholeStageCodegenExec.metrics$lzycompute(WholeStageCodegenExec.scala:528)
    at org.apache.spark.sql.execution.WholeStageCodegenExec.metrics(WholeStageCodegenExec.scala:527)