说我有一个对象,我需要对该对象的成员进行一些操作:arr
。
object A {
val arr = (0 to 1000000).toList
def main(args: Array[String]): Unit = {
//...init spark context
val rdd: RDD[Int] = ...
rdd.map(arr.contains(_)).saveAsTextFile...
}
}
广播的arr
与未广播的有什么区别?
即
val arrBr = sc.broadcast(arr)
rdd.map(arrBr.value.contains(_))
和
rdd.map(arr.contains(_))
我认为对象A
是一个单例对象,因此它将通过Spark中的节点进行传输。
在这种情况下是否有必要使用广播?
答案 0 :(得分:2)
在这种情况下
rdd.map(arr.contains(_))
arr
已针对每个任务进行了序列化
在
期间val arrBr = sc.broadcast(arr)
rdd.map(arrBr.value.contains(_))
每个执行者只能执行一次。
因此,在处理大型数据结构时应使用广播。
答案 1 :(得分:2)
除了拉斐尔的答案之外,还有两点需要提及,这是正确的。您必须始终考虑广播的变量的大小,这个大小不能太大,否则Spark将难以在整个集群中有效分配它。您的情况是:
4B x 1000000 = 4000000B ~ 4GB
已超过默认值4MB,可以通过修改spark.broadcast.blockSize
的{{3}}进行控制。
决定是否使用广播的另一个因素是何时拥有value并希望避免改组。通过广播数据帧,密钥将立即在节点中可用,因此避免了从不同节点检索数据(改组)。