Spark:本地模式下的广播使用情况

时间:2018-04-18 16:33:36

标签: scala apache-spark apache-spark-sql spark-dataframe

我知道广播允许在每台机器上保留一个只读副本,而不是随副本一起发送副本。 但是,我想知道广播在本地模式下是否会产生巨大影响,因为我没有节点集群。 或者在本地模式下不使用广播就可以使用?我只是想了解它的用法。

Spark版本#2.0,Scala版本#2.10 本地模式 - 8Cores CPU 64GB RAM

我有类似下面的内容:

case class EmpDim(name: String,age: Int)

empDF
+-----+-------+------+
|EmpId|EmpName|EmpAge|
+-----+-------+------+
|    1|   John|    32|
|    2|  David|    45|
+-----+-------+------+

deptDF
+------+--------+-----+
|DeptID|DeptName|EmpID|
+------+--------+-----+
|     1|   Admin|    1|
|     2|      HR|    2|
|     3| Finance|    4|
+------+--------+-----+

val empRDD = empDF.rdd.map(x => (x.getInt(0), EmpDim(x.getString(1), x.getInt(2))))

val lookupMap = empRDD.collectAsMap() //Without Broadcast
val broadCastLookupMap: Broadcast[Map[Int,EmpDim]] = sc.broadcast(empRDD.collectAsMap()) //With Broadcast

def lookup(lookupMap:Map[Int,EmpDim]) = udf[Option[EmpDim],Int]((empID:Int) => lookupMap.lift(empID))

val combinedDF = deptDF.withColumn("lookupEmp",lookup(lookupMap)($"EmpID")) //Without Broadcast
                       .withColumn("broadCastLookupEmp",lookup(broadCastLookupMap.value)($"EmpID")) //With Broadcast
                       .withColumn("EmpName",coalesce($"lookupEmp.name",lit("Unknown - No Name to Lookup")))
                       .withColumn("EmpAge",coalesce($"lookupEmp.age",lit("Unknown - No Age to Lookup")))
                       .drop("lookupEmp")
                       .drop("broadCastLookupEmp")

+------+--------+-----+---------------------------+--------------------------+
|DeptID|DeptName|EmpID|EmpName                    |EmpAge                    |
+------+--------+-----+---------------------------+--------------------------+
|1     |Admin   |1    |John                       |32                        |
|2     |HR      |2    |David                      |45                        |
|3     |Finance |4    |Unknown - No Name to Lookup|Unknown - No Age to Lookup|
+------+--------+-----+---------------------------+--------------------------+

在上面的场景中,建议使用广播还是有点矫枉过正?请建议

1 个答案:

答案 0 :(得分:0)

如果这样使用,广播根本就没有价值。

致电时:

lookup(broadCastLookupMap.value)($"EmpID")
根据Scala替换模型,

broadCastLookupMap.value将在本地进行评估。

正确的实施将是:

def lookup(lookupMap: Broadcast[Map[Int, EmpDim]]) = udf[Option[EmpDim],Int](
  (empID:Int) => lookupMap.value.lift(empID)
)

并致电:

lookup(broadCastLookupMap)($"EmpID")

根据实际执行计划可能会产生一些积极影响。本地或非本地模式 - 适用相同的规则

  • 如果在阶段之间(显式或隐式)重复使用数据,则广播可能很有用。
  • 如果数据在管道中只使用一次,标准的闭包/参数处理机制就足够了。

这里没有任何建议第一种情况,因此广播应该是过时的,但如果你想确定,使用实时环境测试两种解决方案并比较结果。

按名称调用也应该有效:

def lookup(lookupMap: => Map[Int,EmpDim]) = udf[Option[EmpDim],Int](
  (empID:Int) => lookupMap.lift(empID)
)