Spark中如何实现right only join操作?
Spark实现right only join的其他可行方案
right only join即最终结果仅保留右表存在、左表无匹配的记录,除了你当前使用的方案外,还有3种更高效的实现方式:
方案1:使用原生right_anti join(最优推荐)
Spark原生支持右反连接语义,直接对应right only join的需求,仅需一次join操作,Spark Catalyst优化器会自动做执行优化,性能最高。
示例代码(关联键为id):
# PySpark 示例 right_only_df = df1.join(df2, on="id", how="right_anti")
// Scala Spark 示例 val rightOnlyDf = df1.join(df2, Seq("id"), "right_anti")
方案2:右外连接+空值过滤
仅需执行一次右外连接,过滤出左表关联键为空的记录,再取右表全量字段即可,性能仅次于原生右反连接。
示例代码:
# PySpark 示例 right_only_df = df1.join(df2, on="id", how="right_outer") \ .filter(df1["id"].isNull()) \ .select(df2["*"])
方案3:小表场景下的关联键取反过滤
如果左表的关联键去重后数据量极小(可完全加载到Driver内存),可以先收集左表所有关联键,直接在右表做过滤,避免shuffle操作:
# PySpark 示例,仅适合左表关联键去重后数据量<10w的场景 left_distinct_ids = df1.select("id").distinct().rdd.flatMap(lambda x: x).collect() right_only_df = df2.filter(~df2["id"].isin(left_distinct_ids))
方案对比
- 生产环境优先选择原生
right_antijoin,无额外计算开销,适配所有数据规模 - 右外连接+空值过滤的方案适合需要同时获取匹配、非匹配两类结果的场景,一次join即可拆分两种数据,避免重复计算
- 你当前使用的右外连接+内连接+
except的方案需要两次join+一次结果集比对,额外产生两次shuffle开销,仅适合临时测试使用 - 关联键取反过滤方案仅适配左表关联键数据量极小的特殊场景,不要在大数据量生产作业中使用
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

