mysql根本不支持full join,是官方明确不实现的设计决策,词法分析阶段即报error 1064,所有版本(含8.0.32)均未注册full token。

MySQL 压根不解析 FULL JOIN,不是分布式问题,是语法层拒识
执行 FULL JOIN 或 FULL OUTER JOIN 时,MySQL 在词法分析阶段就报 ERROR 1064 (42000),根本不会进入查询优化或执行环节。这不是分布式引擎特有的限制,而是所有官方 MySQL 版本(包括 8.0.32)的统一设计:它没注册 FULL 这个 token,也不打算支持。你看到的“某些分布式引擎不支持”,往往只是误把 MySQL 部署在分布式中间件(如 ProxySQL、ShardingSphere)上,底层仍是原生 MySQL 解析器——错误源头不在分布逻辑,而在 SQL 关键字本身不被识别。
PostgreSQL 分布式扩展(如 Citus)禁用 FULL JOIN 是因语义不可控
Citus 允许写 FULL JOIN,但仅限于两表且必须显式括号,例如 (a FULL JOIN b) FULL JOIN c 会直接报错。原因在于:FULL JOIN 的语义依赖“左/右表”二元结构,而分布式环境下中间结果集已含大量 NULL 行;当这个结果再与第三张表做 FULL JOIN 时,“该把 NULL 行算作左表存在还是不存在”没有标准定义,Citus 选择硬性禁止而非模糊实现。此外,若两表分片键不一致(比如 a.user_id 分片,b.order_id 分片),Citus 无法局部执行 FULL JOIN,只能退化为全量广播 + 单节点计算,性能极差,所以默认关闭该路径。
TiDB 和 StarRocks 对 FULL JOIN 的支持依赖分片对齐
TiDB 从 v7.1 开始实验性支持 FULL OUTER JOIN,但仅当两个表的 JOIN 字段同为分片键(shard key)且哈希函数一致时才启用高效执行计划;否则降级为 Broadcast Join 或报错 Unsupported type: FullOuterJoin。StarRocks 更激进:v3.2+ 支持,但要求连接字段必须有统计信息且非 NULL——如果 LEFT JOIN 中 ON 条件含可空字段(如 user.profile_id IS NULL),优化器会直接拒绝生成 FULL JOIN 计划,因为 NULL 传播会导致右表独有行判定失效,结果不可靠。
字段允许 NULL 时,模拟 FULL JOIN 极易漏数据
这是最容易被忽略的坑。当你用 NOT EXISTS 提取右表独有行:SELECT * FROM t2 WHERE NOT EXISTS (SELECT 1 FROM t1 WHERE t1.id = t2.t1_id),若 t1.id 允许 NULL,则子查询中 t1.id = t2.t1_id 永远返回 UNKNOWN,整个条件恒为 FALSE,导致右表所有行都被过滤掉。不能靠改写 WHERE 解决,得提前处理:COALESCE(t1.id, -1) = COALESCE(t2.t1_id, -1) 或建物化视图预清洗 NULL。分布式环境下这个问题更隐蔽——NULL 可能来自不同节点的分片裁剪误差,最终结果缺失却无报错。










