SQL 外连接的执行过程解析
发布时间 - 2026-01-26 00:00:00 点击率:次外连接中驱动表优先匹配,被驱动表需关联字段索引;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) - 用
S可强制按书写顺序执行,但需确认统计信息准确,否则反而更慢
TRAIGHT_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。
这意味着:即使被驱动表完全没数据,只要驱动表有 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 的处理成本常被低估。
# mysql
# js
# json
# ai
# switch
# 内存占用
# red
# sql
# NULL
# select
# format
# 循环
# using
# table
# 算法
# 不支持
# 发生在
# 中对
# 这一
# 子句
# 都要
# 才是
# 而在
# 适用于
# 上有
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
如何基于云服务器快速搭建网站及云盘系统?
iOS发送验证码倒计时应用
如何快速搭建二级域名独立网站?
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
Java解压缩zip - 解压缩多个文件或文件夹实例
如何将凡科建站内容保存为本地文件?
Java遍历集合的三种方式
详解Oracle修改字段类型方法总结
HTML 中如何正确使用模板变量为元素的 name 属性赋值
打开php文件提示内存不足_怎么调整php内存限制【解决方案】
原生JS实现图片轮播切换效果
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
韩国服务器如何优化跨境访问实现高效连接?
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
如何快速建站并高效导出源代码?
音响网站制作视频教程,隆霸音响官方网站?
Laravel如何生成和使用数据填充?(Seeder和Factory示例)
JavaScript如何实现继承_有哪些常用方法
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程
Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】
如何在IIS7中新建站点?详细步骤解析
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
bootstrap日历插件datetimepicker使用方法
Laravel如何处理异常和错误?(Handler示例)
微信小程序制作网站有哪些,微信小程序需要做网站吗?
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
浅析上传头像示例及其注意事项
高端建站三要素:定制模板、企业官网与响应式设计优化
Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】
微信小程序 input输入框控件详解及实例(多种示例)
Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
深圳网站制作的公司有哪些,dido官方网站?
Android 常见的图片加载框架详细介绍
用v-html解决Vue.js渲染中html标签不被解析的问题
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
三星网站视频制作教程下载,三星w23网页如何全屏?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址
Android GridView 滑动条设置一直显示状态(推荐)
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
网站制作免费,什么网站能看正片电影?


