Spark join 什么时候不会触发shuffle有以下几种情况:
- 一种是使用broadcast join,即将小表广播到所有executor,然后在本地进行join,这样就不需要shuffle。spark有一个参数spark.sql.autoBroadcastJoinThreshold
, 默认为10MB,表示当join中的一张表的size小于10MB时,spark会自动将其封装为broadcast发送到所有结点,然后进行broadcast join。当然也可以手动将join中的某张表转化成broadcast : sparkSession.sparkContext.broadcast (df)。
- 另一种是使用bucket join,即将要join的两张表按照join columns(或join columns的子集)根据相同的partitioner预先做好分区,并将这些分区信息存储到catalog中(比如HiveExternalCatalog);然后在读取这两张表并做join时,spark根据bucket信息将两张表的相同partition进行join即可,从而避免了shuffle的过程。注意,这里是避免了shuffle过程,并没有完全避免网络传输,由于两张表的相同partition不一定在同一台机器上,所以这里仍需要对其中一张表的partition进行网络传输。
- 还有一种是使用RDD的join方法,并且参与join的所有rdd的partitioner都和结果rdd的partitioner相同。这样就可以避免shuffle,因为RDD的join实现是由cogroup方法完成的,cogroup中生成了CoGroupedRDD对象,如果它的partitioner和结果CoGroupedRDD的partitioner相同,则该rdd会成为CoGroupedRDD的一个oneToOne窄依赖,否则就是一个shuffle依赖,即宽依赖。