跳转到主内容
极星编程网:以代码为星,赴技术山海!

SQL 外连接的执行过程解析

外连接中驱动表优先匹配,被驱动表需关联字段索引;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。 php版微信js-sdk支付接口类 php版微信js-sdk支付接口类 下载 这意味着:即使被驱动表完全没数据,只要驱动表有 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 的处理成本常被低估。

相关文章