Spark SQL广播散列连接

时间:2016-05-27 15:31:10

标签: apache-spark apache-spark-sql

我尝试使用SparkSQL在数据帧上执行广播散列连接,如下所示:https://docs.cloud.databricks.com/docs/latest/databricks_guide/06%20Spark%20SQL%20%26%20DataFrames/05%20BroadcastHashJoin%20-%20scala.html

在该示例中,(小)DataFrame通过saveAsTable持久化,然后通过spark SQL(即通过sqlContext.sql("..."))

加入

我遇到的问题是我需要使用sparkSQL API来构建我的SQL(我还要加入约50个带有ID列表的表,并且不想手动编写SQL)。

How do I tell spark to use the broadcast hash join via the API?  The issue is that if I load the ID list (from the table persisted via `saveAsTable`) into a `DataFrame` to use in the join, it isn't clear to me if Spark can apply the broadcast hash join.

2 个答案:

答案 0 :(得分:19)

您可以明确地将DataFrame标记为足够小以进行广播 使用broadcast函数:

<强>的Python

from pyspark.sql.functions import broadcast

small_df = ...
large_df = ...

large_df.join(broadcast(small_df), ["foo"])

或广播提示(Spark&gt; = 2.2):

large_df.join(small_df.hint("broadcast"), ["foo"])

<强> Scala的

import org.apache.spark.sql.functions.broadcast

val smallDF: DataFrame = ???
val largeDF: DataFrame = ???

largeDF.join(broadcast(smallDF), Seq("foo"))

或广播提示(Spark&gt; = 2.2):

largeDF.join(smallDF.hint("broadcast"), Seq("foo"))

SQL

您可以使用提示(Spark >= 2.2):

SELECT /*+ MAPJOIN(small) */ * 
FROM large JOIN small
ON large.foo = small.foo

SELECT /*+  BROADCASTJOIN(small) */ * 
FROM large JOIN small
ON large.foo = small.foo

SELECT /*+ BROADCAST(small) */ * 
FROM large JOIN small
ON larger.foo = small.foo

R (SparkR):

使用hint(Spark&gt; = 2.2):

join(large, hint(small, "broadcast"), large$foo == small$foo)

使用broadcast(Spark&gt; = 2.3)

join(large, broadcast(small), large$foo == small$foo)

注意

如果其中一个结构相对较小,则广播连接很有用。否则它可能比完全洗牌要贵得多。

答案 1 :(得分:2)

通过广播连接,连接方程的一侧正在实现并发送给所有映射器。因此,它被视为地图侧连接。

随着数据集的实现和通过网络发送,如果数据集相当小,它只会带来显着的性能提升。

因此,如果您尝试执行 smallDF.join(largeDF)

<强>等待.. !!!另一个限制是它还需要完全适合每个执行器的内存。它还需要适合驱动程序的内存!

使用Torrent协议iePeer-to-Peer协议在执行者之间共享广播变量,Torrent协议的优点是对等体彼此共享文件块,而不依赖于持有所有块的中央实体。 / p>

上面提到的例子足以开始播放广播连接。

注意: 创建后无法修改值。  如果您尝试,只会在一个节点

上进行更改