MySQL执行顺序及注意事项

ppgo8 于 2023-03-17 发布

MySQL执行顺序及注意事项

MySQL语句执行顺序

from           -- 所有都可以使用表别名
on
join
where
group by  
having + 聚合函数
select         -- 这里之后才可以使用列别名 
distinct  
order by
limit 

所有的查询语句都是从from开始执行,执行过程中,每个步骤都会为下一个步骤生成虚拟表,虚拟表将作为下一个步骤的输入。注意,应用程序无法获得虚拟表。

  1. from子句前两个表执行笛卡尔积,生成虚拟表vt1

  2. on筛选器,将on中的逻辑表达式应用的vt1中各个行,筛选满足条件的行,生成虚拟表vt2

  3. 如果是outer join,这一步将添加外部行,生成vt3

    left outer join就添加左表在第二步中被过滤的行

    right outer join就添加右表在第二步中被过滤的行

  4. 如果from后表数量多于2,那么就将vt3和第三个表连接计算笛卡尔积,生成新的虚拟表,重复1-3,最终得到新的虚拟表vt3

  5. where筛选器,筛选vt3,生成虚拟表vt4。

    重要细节

    对于包含outer join子句的查询,到底是应用on还是where?

    on和where最大的区别就是:第二步on应用逻辑表达式,第三步outer join还会把某一边移除的行再次添加回来。而where移除的是最终的。

  6. group by子句将vt4唯一值组合成一组,生成虚拟表vt5。

  7. 应用cube或者roll up选项,为vt5生成超聚合,生成虚拟表vt6。

  8. having筛选器,生成虚拟表vt7。

  9. select子句,筛选vt7中的列,生成vt8。

  10. distinct子句,vt8中移除相同的行,生成vt9。

    事实上,如果应用了group by子句,distinct是多余的。因为分组的时候是将列中的唯一值分成一组,同时为每组返回一行记录,所以所有记录都是不同的。

  11. order by子句。排序vt9,此时返回一个游标,而不是虚拟表。

    除非必须要排序,否则最好不要指定order by,因为这十分花费成本。这里可以使用selece列表中别名的步骤。

12.limit。limit返回结果给用户。

如果是inner join, 放on和放where产生的结果一样, 执行计划也是一样,但推荐使用on


注意的地方