外连接中驱动表优先匹配,被驱动表需关联字段索引;ON决定匹配逻辑,WHERE过滤最终结果;NULL填充无法索引加速,哈希外连接仅在无索引全扫时可能提速。

外连接执行时,驱动表和被驱动表怎么选
外连接的执行顺序不完全由 SQL 写法决定,而取决于优化器对 JOIN 顺序的选择。左外连接(LEFT JOIN)中,左侧表默认为驱动表,右侧表为被驱动表;右外连接(RIGHT JOIN)则相反。但若开启 optimizer_switch='join_cache_level=2' 或存在合适索引,优化器可能重排顺序——此时 EXPLAIN 的 table 列顺序和 type 字段(如 ref vs ALL)才是真实执行路径的关键依据。
常见错误现象:明明写了 LEFT JOIN,却在 WHERE 子句里对右表字段加了非空条件(如 WHERE t2.status = 'active'),结果变成隐式内连接——因为过滤发生在连接后,NULL 行被直接剔除。
- 驱动表应尽量小,或有高选择性索引,减少循环次数
- 被驱动表必须在关联字段上有索引,否则触发全表扫描(
type: ALL) - 用
STRAIGHT_JOIN可强制按书写顺序执行,但需确认统计信息准确,否则反而更慢
ON 条件和 WHERE 条件在外连接中的作用差异
ON 是连接阶段的“匹配规则”,决定哪些行能组成临时结果;WHERE 是连接完成后的“最终过滤”,会筛掉已生成的整行(包括左表数据)。对左外连接来说,ON 中右表条件不满足时,右表字段补 NULL,左表行仍保留;而 WHERE 中对右表字段的限制会让这些 NULL 行消失。
示例:SELECT * FROM orders o LEFT JOIN users u ON o.user_id = u.id AND u.status = 'active' —— 这里 u.status = 'active' 在 ON 中,不影响 orders 行输出;若挪到 WHERE u.status = 'active',则所有无匹配活跃用户或用户为非活跃的订单都会被过滤掉。
-
ON支持对任意表字段做条件,包括被驱动表的非索引字段(但性能差) -
WHERE中对被驱动表字段的等值条件,可能让优化器放弃外连接语义,转为内连接执行 - 多表外连接链(如 A LEFT JOIN B LEFT JOIN C)中,
ON条件只作用于相邻两表,不能跨跳
NULL 值填充发生在哪一步,能否被索引利用
NULL 填充是外连接算法的最后一步:先完成驱动表与被驱动表的匹配(类似内连接逻辑),再将未匹配的驱动表行单独拎出,对其被驱动表字段补 NULL。这个过程发生在存储引擎返回数据之后、Server 层组装结果之前,因此无法被任何索引加速——索引只参与匹配阶段的查找,不参与补 NULL。
Countly 是一个实时的、开源的移动分析应用,通过收集来自手机的数据,并将这些数据通过可视化效果展示出来以分析移动应用的使用和最终用户的行为。截至2019年,支持超过2500个网站,16000个移动应用程序和多个桌面应用程序。它从移动,桌面,Web收集数据包括Apple Watch,TvOS和其他互联网连接设备的应用程序,并将这些信息可视化以分析应用程序使用情况和最终用户行为。
这意味着:即使被驱动表完全没数据,只要驱动表有 100 万行,外连接结果也至少有 100 万行,且每行都要构造一次 NULL 值。如果后续还有 GROUP BY 或 ORDER BY,代价会进一步放大。
- 补 NULL 不触发磁盘 I/O,但增加 CPU 和内存开销(尤其大字段如
TEXT) - 联合索引无法覆盖 “驱动表有值 + 被驱动表无匹配” 这一场景,所以别指望靠索引避免 NULL 行
- 用
EXPLAIN FORMAT=JSON查看filtered字段,若被驱动表的filtered接近 0,说明大量行未匹配,补 NULL 开销已成瓶颈
MySQL 8.0+ 的哈希外连接是否真能提速
MySQL 8.0.18 引入了哈希外连接(Hash Outer Join),但仅适用于被驱动表走全表扫描(type: ALL 或 type: index)且无合适索引的场景。它把驱动表建哈希表,再流式扫描被驱动表做探测。相比嵌套循环,它减少了随机 I/O,但内存占用更高,且不支持被驱动表使用索引查找(即不兼容 ref/eq_ref)。
是否启用由优化器自动判断,可通过 SET optimizer_switch='hash_join=on' 手动打开,但需注意:若驱动表太大导致哈希表溢出磁盘,性能反而暴跌;且哈希连接不支持 USING 语法,只认 ON 显式条件。
- 查看
EXPLAIN输出中Extra是否含Using where; Using join buffer (hash join) - 哈希外连接无法下推
WHERE条件到被驱动表扫描前,所以过滤越晚,扫描越多 - 小数据量(
外连接的真实开销往往不在连接本身,而在补 NULL 后的数据流转——比如后续排序、聚合、网络传输,这些环节对 NULL 的处理成本常被低估。









