Scala Spark DataFrame内连接后仅获取右表全列的最优方案
问题根因
当使用Seq类型的字段列表作为Join条件执行等值Join时,Spark会自动合并左右表的Join键为公共列,该公共列不属于任何一个表的别名命名空间,因此直接通过dfy.*选取右表所有列时,无法获取到合并后的Join键列。
最优解决方案
方案1:使用right_semi类型Join(Spark 3.0+ 推荐,性能最优)
right_semi Join是专门为该场景设计的Join类型,只会返回右表中能和左表匹配上Join键的所有行,且直接返回右表全部原始列,不需要额外处理列选择,性能优于普通内连接后再过滤选列的方案。
代码示例:
df1.as("dfx").join(df2.as("dfy"), joinKey.split(",").toSeq, "right_semi").show()
输出结果:
+---+-----+ | id|value| +---+-----+ | 1| C| +---+-----+
完全符合需求,没有冗余数据,也不会丢失Join键。
方案2:通用动态列选择(兼容所有Spark版本)
如果使用低于3.0的Spark版本,不支持right_semi Join,可以动态拼接需要选取的列,不需要硬编码列名,适配任意数量的Join键:
val joinKeys = joinKey.split(",").toSeq // 拼接选择列:先选公共Join键,再选右表非Join键列 val selectCols = joinKeys.map(col) ++ df2.columns.filterNot(joinKeys.contains).map(c => col(s"dfy.$c")) df1.as("dfx").join(df2.as("dfy"), joinKeys, "inner") .select(selectCols: _*) .show()
输出结果和方案1完全一致。
内容的提问来源于stack exchange,提问作者Gadam
相关产品推荐
相关产品推荐

