Spark 3.3.2(EMR 6.11)出现Union分析异常,3.4.0无此问题
问题分析与解决方案
这是Spark 3.3.x版本的已知问题,和执行计划优化逻辑直接相关,具体细节如下:
问题根源
你代码中使用的unionByName(allowMissingColumns=True)本身逻辑是对的,但在Spark 3.3.x中,优化器的CollapseUnions规则会将逻辑计划中的UnionByName节点转换为普通Union节点,却没有同步保留allowMissingColumns=True的配置。这种自动转换后的普通Union会严格校验列数,导致你看到的列数不匹配异常。因为异常堆栈指向的是优化后生成的执行计划节点,而非你手写的代码,所以你看不到自己代码里有Union逻辑。
版本修复情况
该问题已在Spark 3.4.0中通过SPARK-40565修复,修复后优化器会正确识别UnionByName的参数,不会错误转换为普通Union,这也是你本地测试Spark 3.4.0时问题消失的原因。
临时解决方案(针对Spark 3.3.x)
- 禁用特定优化规则:在Spark配置中添加
spark.sql.optimizer.excludedRules=org.apache.spark.sql.catalyst.optimizer.CollapseUnions,阻止优化器转换UnionByName节点。注意:这会关闭该规则对所有查询的优化,可能影响部分查询的执行性能。 - 手动对齐列:在执行
unionByName前,手动为列数少的DataFrame添加缺失列并设置默认值(比如lit(null).alias("缺失列名")),确保两个DataFrame列数一致,绕开优化器的问题。
异常信息
spark.sql.utils.AnalysisException: Union can only be performed on tables with the same number of columns, but the first table has 7 columns and the second table has 6 columns
内容的提问来源于stack exchange,提问作者Srivatsan Nallazhagappan
相关产品推荐
相关产品推荐

