0%

MySQL执行顺序

MySQL SQL 语句执行顺序详解

MySQL 执行 SQL 语句时,并不是按照代码的书写顺序执行的,而是遵循一套固定的逻辑流程。理解执行顺序对于编写高效 SQL、排查查询问题至关重要。

完整执行顺序

MySQL 对 SQL 语句的执行顺序如下(按序号依次执行):

  1. FROM 及关联操作
    • 首先确定查询的数据源,包括主表(FROM <left_table>)和关联表(<join_type> JOIN <right_table>)。
    • 通过 ON <join_condition> 过滤关联条件,生成临时数据集(包含两表匹配的记录)。
  2. WHERE 过滤
    • FROM 阶段生成的临时数据集进行行级过滤,仅保留满足 <where_condition> 的记录。
    • 注意:此时还不能使用 SELECT 中定义的别名,也不能使用聚合函数(如 SUM()COUNT())。
  3. GROUP BY 分组
    • <group_by_list> 指定的字段对数据进行分组,相同分组的记录会被合并为一行。
    • 分组后,后续操作(如 HAVINGSELECT)只能针对分组后的结果进行处理。
  4. HAVING 过滤
    • GROUP BY 分组后的结果进行过滤,仅保留满足 <having_condition> 的分组。
    • WHERE 的区别:HAVING 可使用聚合函数(如 HAVING COUNT(*) > 10),而 WHERE 不行。
  5. SELECT 字段筛选
    • 从前面的结果集中筛选出 <select_list> 指定的字段或计算结果(如 SELECT name, age+1 AS new_age)。
    • 此时可以使用别名(如 new_age)。
  6. DISTINCT 去重
    • SELECT 阶段的结果进行去重,保留唯一的记录。
  7. ORDER BY 排序
    • <order_by_condition> 对结果集进行排序(如 ORDER BY age DESC)。
    • 可以使用 SELECT 中定义的别名(如 ORDER BY new_age)。
  8. LIMIT 限制结果
    • <limit_number> 截取结果集的前 N 行(如 LIMIT 10 取前 10 行,LIMIT 5,10 从第 5 行开始取 10 行)。

关键阶段解析

1. FROMJOIN 阶段

  • 先加载主表和关联表的数据,通过 ON 条件筛选匹配的记录(而非 WHERE)。
  • 例:SELECT * FROM a JOIN b ON a.id = b.a_id WHERE a.status = 1 中,ON 先筛选两表关联关系,再通过 WHERE 过滤主表状态。

2. WHEREHAVING 的区别

特性 WHERE HAVING
执行阶段 GROUP BY 之前 GROUP BY 之后
作用对象 原始行数据 分组后的结果
支持聚合函数 不支持(如 COUNT() 支持(如 COUNT(*) > 5
支持别名 不支持(SELECT 未执行) 支持(SELECT 已执行)

3. ORDER BY 的特殊性

  • 排序操作在 SELECT 之后,因此可以使用 SELECT 中定义的别名(如 SELECT age AS a ORDER BY a)。
  • 若未使用索引排序,会触发 Using filesort(文件排序),可能影响性能。

示例验证

以下 SQL 的执行流程:

1
2
3
4
5
6
7
8
9
10
SELECT 
department,
AVG(salary) AS avg_salary
FROM employee
JOIN dept ON employee.dept_id = dept.id
WHERE hire_year > 2020
GROUP BY department
HAVING avg_salary > 10000
ORDER BY avg_salary DESC
LIMIT 3;
  1. FROM + JOIN + ON:关联 employeedept 表,通过 employee.dept_id = dept.id 匹配记录。
  2. WHERE:筛选出 2020 年后入职的员工(hire_year > 2020)。
  3. GROUP BY:按 department 字段分组。
  4. HAVING:保留平均工资大于 10000 的部门(avg_salary > 10000)。
  5. SELECT:提取 department 和平均工资(avg_salary)。
  6. ORDER BY:按 avg_salary 降序排序。
  7. LIMIT:取前 3 条结果

欢迎关注我的其它发布渠道