一、首先我们看一下mysql的sql语句的书写顺序 。

select--distinct--from--on--where--group by--having--聚合函数cube、rollup--order by--limit--集合运算UNION,EXCEPT和INTERSECT

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

二、MySQL的语句执行顺序,这个可以从官方文档查看 ,也可以自己测试。

from -> on -> join -> where -> group by -> 聚集函数 cube|rollup -> having -> select -> 去重Distinct ->集合操作-> 排序order by -> 抽取分页limit
MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是 FROM操作,最后执行的是LIMIT(条数)操作。其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明 的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。

方法/步骤
下面我们来具体分析一下查询处理的每一个阶段
1. FROM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1
2. ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。
3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3,
run from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为 止。
4. WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。
5. GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
6. CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
7. HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。
8. SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
9. DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
10. ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10.
11. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。
END

三、简要分析子句作用和执行方式,特意对应sql执行顺序

可以充分考虑执行顺序和执行方式和执行开销,灵活调整sql,加快执行速度。布尔表达式的位置可以直接用true和false加入测试验证一下
from--where--group by--聚合函数--having--select--distinct--union all--order by--limit

from:数据来源,需要从哪个数据表检索数据          从右向左,从下向上(←↑)
on:连接表进行过滤,布尔表达式 。用逗号分隔的多个条件是 从右向左,从下向上(←↑),而单个布尔表达式内部是从左向右,会触发短路效果(比如先执行and和or的左侧)。                                                              
join:数据来源,高开销,按on条件保留驱动表未连接数据
where:过滤表中数据的条件,布尔表达式,可以使用等号起到连接的作用 。 用逗号分隔的多个条件是 从右向左,从下向上(←↑),而单个布尔表达式内部是从左向右,会触发短路效果(比如先执行and和or的左侧)。                           
group by:如何将上面过滤出的数据分组 ,通常将group by 的字段放到select子句里,从上到下,左到右(→↓)
cube,rollup:聚集函数,高开销,聚合函数(统计用 sum,avg,max,min等)
having:对上面已经分组的数据进行过滤的条件 ,布尔表达式,高开销
select:获取结果集,或列的计算结果 ,筛选结果列
distinct:针对字段去除结果集重复行
union all,union,except,intersect :对结果集进行集合操作,差集,并集等,多个分句从左向右,从上到下,左到右(→↓),最左分句先开始。
order by:按字段排序结果集。高开销,多字段从左向右从上向下执行 (→↓)
limit :和oracle的伪列 rownum对应执行位置,sqlserver的 top对应执行位置。都是最后执行的。在一个where子句里rownum和top的位置不影响执行结果。截掉多余的数据,保留剩余结果集。
针对表和多个条件从右向左执行,针对结果集、字段、布尔表达式是从左向右执行。

 

四、sql子句的默认行为总结

 

  1.group by语句有默认的排序行为

  2.union 子句默认会去重排序

五、因为sql优化和很多因素相关 ,例如下面这些,我会在本系列逐项解析。

1.sql语句内的执行顺序 和执行开销
2.sql从执行到输出的全生命周期
3.sql执行计划
4.缓存的存在和调用
5.表结构(schama),索引和视图
6.数据量 和 数据存储结构 
7.所用数据库(schama)
8.数据库执行引擎
9.cpu性能和内存占用
10.磁盘IO和网络

2018-10-14

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄