Apache spark 火花复用广播测向

Apache spark 火花复用广播测向,apache-spark,Apache Spark,我想重用我的数据帧(而不是使用RDD/Dataset中的“Map”函数),我将其标记为可广播,但Spark似乎一次又一次地广播它 有一个表“银行”(测试表)。我执行以下操作: val cachedDf = spark.sql("select * from bank").cache cachedDf.count val dfBroadcasted = broadcast(cachedDf) val dfNormal = spark.sql("select * from bank

我想重用我的数据帧(而不是使用RDD/Dataset中的“Map”函数),我将其标记为可广播,但Spark似乎一次又一次地广播它

有一个表“银行”(测试表)。我执行以下操作:

  val cachedDf = spark.sql("select * from bank").cache
  cachedDf.count

  val dfBroadcasted = broadcast(cachedDf)

  val dfNormal = spark.sql("select * from bank")

  dfNormal.join(dfBroadcasted, List("age"))
    .join(dfBroadcasted, List("age")).count
我在缓存之前只是为了以防万一,但不管有没有,都是一样的

如果执行上述代码,我会看到以下SQL计划:

如您所见,我的广播DF广播两次,时间也不同(如果我在之后添加更多操作,它们也会再次广播)

我关心这一点,因为我实际上有一个长期运行的程序,它有一个“大”数据帧,我可以用它来过滤出巨大的数据帧,我希望这个“大”数据帧能够被重用

有没有一种方法可以强制重用?(不仅在同一个动作中,而且在动作之间,我可以用同一个动作生存)


谢谢

好的,更新问题

总结: 在同一个动作中,left_semis将重用广播 而普通/左连接不会。不确定与Spark/开发人员已经知道DF的列根本不会影响输出的事实有关,因此他们可以重用它,或者只是缺少一个优化Spark

我的问题似乎基本上解决了,不过如果有人知道如何在整个行动中保持广播效果,那就太好了。

如果我使用left_semi(这是我将在我的真实应用程序中使用的连接),则广播只执行一次

与:

计划变为(我还更改了大小,使其与我的真实尺寸相匹配,但这没有任何区别):

此外,墙总时间比使用“left_semi”时要好得多(我设置了1个executor,这样它就不会被并行化,只是想检查工作是否真的完成了两次):


尽管我的收集需要10秒,但这将加快表读取+分组速度,这需要6-7分钟

缓存数据广播怎么样?@mangusta尝试过,也没用,不管我缓存之前还是之后。还尝试了spark.sql.autoBroadcastJoinThreshold-1您确定它会广播两次吗?仅仅因为SQL计划可视化程序只是优化计划的简单高级翻译,它往往会隐藏某些部分。按照我的理解,它是在代码中编写的,表是缓存的,InMemoryTable扫描(即缓存的扫描)用于每个连接,可以并行处理。。。但我建议让Spark Optimizer来决定何时需要广播,因为向每个节点广播一个巨大的表并立即填满所有执行器内存不是一个好主意。嗨,Richard,这就是为什么我要指出计时的原因,两个可视化器都显示不同的计时,所以我打赌它会被执行两次(否则,它应该有相同的时间)。Spice优化器不知道该表的大小,因为它不是来自蜂箱(它是在执行的中间生成的)。我的真实表是600万个注册表(它只是每行两个小字符串)。,但在执行任何洗牌操作之前,它可以用于筛选具有许多列的6000万个注册表的表。因此,跨操作的一般语句不正确,这是一个特殊情况。很有趣。
    dfNormalxx.join(dfBroadcasted, Seq("age"),"left_semi")
.join(dfBroadcasted, Seq("age"),"left_semi").count