PySpark获取四类join输出的两种实现方案哪种效率更高?
Spark 多Join结果生成方案效率对比
场景说明
需要生成4个专用join结果:
- df1:left_anti join结果
- df2:left_semi join结果
- df3:right_anti join结果
- df4:right_semi join结果
对比两种实现方案的效率。
方案1:1次全外连接+4次过滤
join_condition = (sf.col('left_df.col1') == sf.col('right_df.col1')) merged_df = left_df.join(right_df, join_condition, how='full_outer') df1 = merged_df.filter(sf.col('right_df.col1').isNull()).select('left_df.*') df2 = merged_df.filter(sf.col('right_df.col1').isNotNull()).select('left_df.*') df3 = merged_df.filter(sf.col('left_df.col1').isNull()).select('right_df.*') df4 = merged_df.filter(sf.col('left_df.col1').isNotNull()).select('right_df.*')
注:col1为两表主键,均为非空字段。
方案2:4次专用join
join_condition = (sf.col('left_df.col1') == sf.col('right_df.col1')) df1 = left_df.join(right_df, join_condition, how='left_anti') df2 = left_df.join(right_df, join_condition, how='left_semi') df3 = left_df.join(right_df, join_condition, how='right_anti') df4 = left_df.join(right_df, join_condition, how='right_semi')
最终结论
绝大多数生产级大数据场景下,方案2的执行效率远高于方案1,仅在两个输入DataFrame均为KB级极小数据量的极端场景下二者性能接近。
效率差异核心原因
- 专用join算子的原生优化:Spark的semi、anti类join属于存在性校验算子,执行时仅需要判断join键的匹配关系,不需要拉取另一端表的非join字段,也不需要保留多匹配行结果,shuffle阶段仅需要传输join键数据,数据传输量比全外连接低数倍甚至数十倍。
- 全外连接中间表开销过大:方案1的full_outer join会生成包含左右表所有行的大体积中间宽表,不仅shuffle阶段需要传输左右表全量字段,后续4次过滤操作也需要全量扫描这个大中间表,额外增加了大量内存、磁盘IO开销,若存在join键数据倾斜,全外连接的性能衰退会比专用join严重得多。
- 结果完全等价:因为col1是两表的非空主键,两种方案的输出结果完全一致,不存在正确性差异。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

