一、SQL执行循序
SQL单表执行循序
SELECT * FROM XXX WHERE XX = XX1.先执行FROM的表
2.在执行相应的WHERE条件
3.在执行SELECT查询
SQL多表执行循序
SELECT DISTINCT(XX) FROM XXX(left_table)
[join_type(left/right/all)] JOIN (right_tanle) ON left.XX = right.XX (left/right 两表相等的条件)
WHERE XX = XX
GROUP BY XX(Group by 相应的字段)
WITH{XX}
HAVING XX (having 相应字段)
ORDER BY XX (Order by 相应的字段)
LIMIT XX (Limit XX 分页)
1.先执行FROM的表
2.执行多表关联的ON条件
3.执行多表关联的JOIN表
4.执行相应的WHERE条件
5.执行GROUP BY分组
6.执行WITH子查询部分
7.执行HAVING 聚合函数
8.执行SELECT查询
9.执行DISTINCT去重
10.执行ORDER BY排序
11.执行LIMIT分页
二、执行过程
不同的数据库执行过程有差异,下面介绍两种主流的数据库(Oracle、Mysql):
- 用户提交了一条SQL语句
- 数据库按照SQL语句的字面值计算出一个HASH值
- 根据HASH值,判断一下在数据库缓冲区中是否存在此SQL的执行计划。
- 如果不存在,则需要生成一个执行计划(硬解析过程),然后将结果存入缓冲区。
- 如果存在的话,判断是否为相同SQL(同样HASH值的语句,可能字符不相同;即使完全相同,也可能代表不同的语句。这块不展开说了)
- 确认是同一条SQL语句,则从缓冲区中取出执行计划。
- 将执行计划,交给执行器执行。
- 结果返回给客户端。
- 客户提交一条语句
- 现在查询缓存查看是否存在对应的缓存数据,如有则直接返回(一般有的可能性极小,因此一般建议关闭查询缓存)。
- 交给解析器处理,解析器会将提交的语句生成一个解析树。
- 预处理器会处理解析树,形成新的解析树。这一阶段存在一些SQL改写的过程。
- 改写后的解析树提交给查询优化器。查询优化器生成执行计划。
- 执行计划交由执行引擎调用存储引擎接口,完成执行过程。这里要注意,MySQL的Server层和Engine层是分离的。
- 最终的结果有执行引擎返回给客户端,如果开启查询缓存的话,则会缓存。
三、执行计划
Mysql执行计划
Explain语法
EXPLAIN SELECT * FROM TABLE_NAME ...
变体:
1. EXPLAIN EXTENDED SELECT * FROM TABLE_NAME ...
将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得到被MySQL优化器优化后的查询语句
2. EXPLAIN PARTITIONS SELECT * FROM TABLE_NAME ...
用于分区表的EXPLAIN
ID
包含一组数字,表示查询中执行select子句或操作表的顺序,id相同执行顺序由上至下;如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行
Select_type
Type
由左至右,由最差到最好
a.ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
b.index:Full Index Scan,index与ALL区别为index类型只遍历索引树
c.range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询
range访问类型的不同形式的索引访问性能差异
d.ref:非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找
f.const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量
system是const类型的特例,当查询的表只有一行的情况下, 使用system
g.NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引
Possible_keys
Key
Key_len
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
ref
Extra