在Spark 1.6中加入数据帧时没有发生广播

时间:2016-02-05 23:46:51

标签: scala apache-spark join apache-spark-sql query-optimization

以下是我正在运行的示例代码。当这个spark作业运行时,使用sortmergejoin而不是broadcastjoin发生Dataframe连接。

def joinedDf (sqlContext: SQLContext,
              txnTable:   DataFrame,
              countriesDfBroadcast: Broadcast[DataFrame]): 
              DataFrame = {
                    txnTable.as("df1").join((countriesDfBroadcast.value).withColumnRenamed("CNTRY_ID", "DW_CNTRY_ID").as("countries"),
                    $"df1.USER_CNTRY_ID" === $"countries.DW_CNTRY_ID", "inner")
              }
joinedDf(sqlContext, txnTable, countriesDfBroadcast).write.parquet("temp")  

即使我在join语句中指定了broadcast()提示,也不会发生broadcastjoin。

优化器对数据帧进行哈希分区,导致数据偏斜。

有没有人见过这种行为?

我使用Spark 1.6和HiveContext作为SQLContext在纱线上运行。火花作业在200个执行器上运行。并且txnTable的数据大小为240GB,countriesDf的数据大小为5mb。

1 个答案:

答案 0 :(得分:8)

广播DataFrame的方式和访问方式都不正确。

  • 标准广播不能用于处理分布式数据结构。如果您想在DataFrame上执行广播加入,则应使用broadcast函数标记给定DataFrame广播:

    import org.apache.spark.sql.functions.broadcast
    
    val countriesDf: DataFrame = ???
    val tmp: DataFrame = broadcast(
      countriesDf.withColumnRenamed("CNTRY_ID", "DW_CNTRY_ID").as("countries")
    ) 
    
    txnTable.as("df1").join(
      broadcast(tmp), $"df1.USER_CNTRY_ID" === $"countries.DW_CNTRY_ID", "inner")
    

    在内部,它collect tmp之后不会转换为内部广播和广播。

  • 热烈评估
  • 加入参数。即使可以在分布式数据结构中使用SparkContext.broadcast,也可以在调用join之前在本地评估广播值。那'为什么你的功能完全有效,但没有进行广播连接。