广播变量,初始的时候在driver上有一份副本。task在运行的时候,想要使用广播变量中的数据,首先会在本地的executor对应的BlockManager中尝试获取变量副本;如果没有,就从driver远程拉取变量副本,并保存在本地的BlockManager中;此后这个executor上的task,都会直接使用本地BlockManager中的副本。executor的BlockManager除了从driver上拉取,也可能从其他节点的BlockManager上拉取变量副本,越近越好。
默认情况下,1000个task,1000份副本。10G的数据,网络传输;在集群中,耗费10G的内存资源。
如果使用广播变量。50个executor,50个副本。500M的数据,从driver或最近节点拉取变量副本,网络资源;耗费500M的内存消耗。两者比较将近20倍的网络传输性能差距;20倍的内存消耗减少。
在sparksql中,当维度表和事实表进行join操作时,为了避免shuffle,我们可以将大小有限的维度表全部数据分发到每个节点上,供事实表使用。executor存储维度表的全部数据,一定程度上牺牲了空间,换取shuffle操作大量的耗时,这在sparksql中称为Broadcast Join.
Broadcast Join的条件如下:
1、被广播的表需要小于spark.sql.autoBroadcastJoinThreshold所配置的值,默认是10M(或者加了broadcast join的hint)
2、基表不能被广播,比如 left outer join时,只能广播右表