MySQL执行顺序及注意事项
MySQL语句执行顺序
from -- 所有都可以使用表别名
on
join
where
group by
having + 聚合函数
select -- 这里之后才可以使用列别名
distinct
order by
limit
所有的查询语句都是从from开始执行,执行过程中,每个步骤都会为下一个步骤生成虚拟表,虚拟表将作为下一个步骤的输入。注意,应用程序无法获得虚拟表。
-
from子句前两个表执行笛卡尔积,生成虚拟表vt1
-
on筛选器,将on中的逻辑表达式应用的vt1中各个行,筛选满足条件的行,生成虚拟表vt2
-
如果是outer join,这一步将添加外部行,生成vt3
left outer join就添加左表在第二步中被过滤的行
right outer join就添加右表在第二步中被过滤的行
-
如果from后表数量多于2,那么就将vt3和第三个表连接计算笛卡尔积,生成新的虚拟表,重复1-3,最终得到新的虚拟表vt3
-
where筛选器,筛选vt3,生成虚拟表vt4。
重要细节:对于包含outer join子句的查询,到底是应用on还是where?
on和where最大的区别就是:第二步on应用逻辑表达式,第三步outer join还会把某一边移除的行再次添加回来。而where移除的是最终的。
-
group by子句将vt4唯一值组合成一组,生成虚拟表vt5。
-
应用cube或者roll up选项,为vt5生成超聚合,生成虚拟表vt6。
-
having筛选器,生成虚拟表vt7。
-
select子句,筛选vt7中的列,生成vt8。
-
distinct子句,vt8中移除相同的行,生成vt9。
事实上,如果应用了group by子句,distinct是多余的。因为分组的时候是将列中的唯一值分成一组,同时为每组返回一行记录,所以所有记录都是不同的。
-
order by子句。排序vt9,此时返回一个游标,而不是虚拟表。
除非必须要排序,否则最好不要指定order by,因为这十分花费成本。这里可以使用selece列表中别名的步骤。
12.limit。limit返回结果给用户。
如果是inner join, 放on和放where产生的结果一样, 执行计划也是一样,但推荐使用on。
注意的地方
-
inner join和outer join,on条件相当于是一个where条件。
因为MySQL都会将on后面的条件优化到where里
-
where和group by字段后不能使用列别名。order by可以
-
union排在order by之前,在union操作后可能不保持原来排序的顺序
-
MySQL中SQL的逻辑查询根据上述进行查询,但MySQL可能并不完全按照逻辑查询方式处理。MySQL两个组件
- 分析器
- 优化器
MySQL在执行查询前,会选择一条自认为最优的方案执行获得查询结果。
-
存在索引,优化器优先使用索引。当索引为多个时,优化器选择效率最高的索引。
-
where查询优化
在数据量较多的时候,建议将排除数据量最多的条件放在第一个。