SQL执行顺序深度解析(附魔性记忆口诀)
看到这个SQL语句,我们先拆解它的执行顺序。根据SQL标准规范,实际执行顺序与书写顺序完全不同,可以用"服了Join昂,威哥还选欧"来记忆(对应中文谐音):
From → Join → On → Where → Group by → Having → Select → Order by
执行流程拆解(含核心组件)
1️⃣ FROM + JOIN(存储引擎)
- 先加载
t1和t2表数据,通过存储引擎(如InnoDB)读取磁盘数据 - 使用B+树索引快速定位数据(如有索引)
2️⃣ ON(执行器)
- 执行连接条件过滤
t1.id=t2.id - 生成临时结果集(可能使用Hash Join或Nested Loop Join)
3️⃣ WHERE(执行器)
- 对连接后的结果进行行级过滤
- 如果存在覆盖索引,可能触发索引下推优化
4️⃣ GROUP BY(临时表)
- 创建内存临时表(或磁盘临时表)进行分组
- 使用
Using filesort时会进行排序分组
5️⃣ HAVING(执行器)
- 对分组后的结果进行二次过滤
- 可理解为分组后的WHERE
6️⃣ SELECT(执行器)
- 最后才执行字段选择
- 计算表达式/聚合函数(如COUNT/SUM)
7️⃣ ORDER BY(排序缓冲区)
- 使用sort_buffer进行排序
- 可能触发文件排序(FileSort)
魔性记忆法(保你忘不掉)
"服了Join昂,威哥还选欧"
- 服(FROM) → 了(JOIN) → 昂(ON)
- 威(WHERE) → 哥(GROUP BY) → 还(HAVING)
- 选(SELECT) → 欧(ORDER BY)
配合这个场景记忆:程序员小明被SQL执行顺序搞崩溃了,仰天长叹"服了Join昂!",他的好基友威哥说"别慌,还选欧(洲杯)看球去!"
高频面试考点
- WHERE和HAVING的本质区别:行过滤 vs 组过滤
- GROUP BY隐式排序陷阱(MySQL 8.0已取消)
- 索引失效的典型场景(如WHERE中使用函数)
- 临时表产生条件(GROUP BY/ORDER BY无索引)
理解这个执行顺序,就能明白为什么WHERE里不能用SELECT别名,而HAVING可以。这也是SQL优化的核心逻辑——尽量在早期阶段减少数据量。