Spark在YARN与K8s环境中广播Join行为差异原因咨询
统计信息不一致:Spark的广播Join决策完全依赖表的统计数据(行数、预估大小)。虽然两边指向同一Hive元数据,但K8s环境里可能没及时更新或加载表的统计信息——比如Hive元数据里的统计过时,或者Spark在K8s中没执行过
ANALYZE TABLE生成最新统计,导致估算的表大小超过了广播阈值;而YARN环境之前可能跑过统计更新,或者自动拉取到了准确的统计值,触发了广播。隐性配置差异:别光看
spark.sql.autoBroadcastJoinThreshold相同,其他相关配置可能不一样。比如spark.sql.statistics.fallBackToHdfs在K8s里被禁用,导致Spark没法通过HDFS文件大小估算表规模;或者spark.sql.cbo.enabled状态不一致——YARN开了基于成本的优化器(CBO),能更精准判断是否该广播,K8s没开的话,估算逻辑就粗糙了。另外spark.sql.join.preferSortMergeJoin如果在K8s里设为true,且表大小接近阈值,Spark可能优先选Sort Merge Join而非广播。资源感知差异:Spark在不同集群里对资源的判断不一样。YARN节点内存充足,Driver觉得广播这张表不会爆内存;但K8s里Driver或Executor的内存配额低,Spark为了避免OOM,自动跳过了广播。还有K8s调度器可能让Spark获取的资源信息不准,也会影响优化器的决策。
数据访问层面的偏差:虽然HDFS路径一样,但K8s环境可能因为网络挂载、权限或者HDFS客户端版本问题,导致Spark读表时拿到的文件大小、块信息不准。比如K8s里的HDFS客户端读不到正确的文件副本数或实际占用空间,估算出来的表大小偏大,超过了广播阈值。
Spark版本或优化器细节差异:如果YARN和K8s用的Spark版本不一样,哪怕配置相同,优化器的底层逻辑也可能有区别。比如不同版本里广播阈值的计算方式、统计数据的优先级判断不同,自然会导致决策差异。
内容的提问来源于stack exchange,提问作者ASR

