mysql(1):简介
SQL语法顺序和执行顺序
SQL语法顺序
SELECT [DISTINCT] <select_list>
FROM <left_table>
<join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
ORDER BY <order_by_condition>
LIMIT <limit_number>
SQL执行顺序
(8)SELECT(9)DISTINCT <select_list>
(1)FROM <left_table>
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)<sum()avg()等聚合函数>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_condition>
(11)LIMIT <limit_number>
第一步:加载from子句的前两个表计算笛卡尔积,生成虚拟表vt1;
第二步:筛选关联表符合on表达式的数据,保留主表,生成虚拟表vt2;
第三步:如果使用的是外连接,执行on的时候,会将主表中不符合on条件的数据也加载进来,做为外部行
【如果from子句中的表数量大于2,则重复第一步到第三步,直至所有的表都加载完毕,更新vt3】
第四步:执行where表达式,筛选掉不符合条件的数据生成vt4;
第五步:执行group by子句。group by 子句执行过后,会对子句组合成唯一值并且对每个唯一值只包含一行,生成vt5。一旦执行group by,后面的所有步骤只能得到vt5中的列(group by的子句包含的列)和聚合函数。
第六步:执行聚合函数,生成vt6;
第七步:执行having表达式,筛选vt6中的数据,生成vt7;
第八步:从vt7中筛选列,生成vt8;
第九步:执行distinct,对vt8去重,生成vt9。其实执行过group by后就没必要再去执行distinct,因为分组后,每组只会有一条数据,并且每条数据都不相同。
第十步:对vt9进行排序,此处返回的不是一个虚拟表,而是一个游标,记录了数据的排序顺序,此处可以使用别名;
第十一步:执行limit语句,将结果返回给客户端
MySQL架构分析和执行流程分析
逻辑架构
连接器
服务管理
连接池
SQL接口
解析器
查询优化器
查询缓存
可插拔存储引擎
MyISAM
InnoDB
Memory
第一层是链接线程处理,这一层并非MySQL独有,在这一层中,主要功能有链接处理,授权验证,安全等操作。
第二层是MySQL主要层,所有的语句解析、分析、优化和缓存都在这一层进行,同时内建函数,如日期、时间等函数也在这一层进行。
第三层中所有的跨存储引擎的功能都在该层完成,例如视图、存储过程、触发器等。
第四层为存储引擎,负责数据的获取和存储。在该层提供了许多API供上层服务层调用,完成数据操作。存储引擎不能解析SQL,互相之间也不能通信。仅仅是简单的响应服务器的请求。
执行流程
1、客户端/服务器通信协议
该部分为半双工状态,要么是客户端向服务器发送数据,要么是服务器向客户端发送数据,二者不能同时进行。
当客户端向服务器发送数据时,以单独一个数据包的形式发送。若查询太大,服务器会拒绝接收更多的数据,并抛出异常;
当服务器向客户端发送数据时,一般包括多个数据包。客户端必须完整的接收所有的数据,不能拒绝接收部分数据只获取前几条。
在开发过程中应该尽量保持简单和必要的查询,这也是减少select *和加上limit限制的原因。
2、查询缓存
在解析查询语句之前,如果开启了查询缓存,MySQL会检查当前查询是否命中缓存中的数据,如果命中,检查用户权限后会直接将缓存中的数据响应给客户端,否则会执行后面的解析等操作。
MySQL的缓存存放在一个引用表中,以一个哈希值作为索引。该索引包含了一系列与查询有关的信息,例如查询本身、要查询的表等。当查询语句中包含函数、用户变量、临时表时就不会存入缓存。
MySQL的缓存也存在失效的状态,所有会影响查询结果的信息都会糅合进一个哈希值作为索引,所以当某一个表的数据或者结构发生变化时(即对某表执行写操作时),该表所涉及到的所有缓存都会失效。当查询缓存非常大时,这个操作会造成较大的系统消耗。
在读操作时,每一个查询语句执行前都会检查是否命中缓存,执行后都会存入缓存。是否打开缓存应慎之又慎。
3、语法解析及预处理
语法解析会通过关键字将查询语句进行解析,生成一棵解析树,这个过程主要是通过语法进行检查。
预处理会将解析树再次进行解析,会检查查询所包含的表、列等是否存在。
4、查询优化
一条语句有多种实现方式,优化器的作用就是评估执行成本并且选择成本最小的那一个。优化器会对执行顺序进行重新排序并执行,选出MySQL认为的最优解。
MySQL的查询优化器是一个非常复杂的部件,它使用了非常多的优化策略来生成一个最优的执行计划:
-
重新定义表的关联顺序
-
优化MIN()和MAX()函数(找某列的最小值,如果该列有索引,只需要查找B+Tree索引最左端,反之则可以找到最大值)
-
提前终止查询(比如:使用Limit时,查找到满足数量的结果集后会立即终止查询)
-
优化排序(老版本:两次传输排序,即先读取行指针和需要排序的字段在内存中对其排序,然后再根据排序结果去读取数据行;新版本:单次传输排序,也就是一次读取所有的数据行,然后根据给定的列排序。对于I/O密集型应用,效率会高很多)
5、查询执行引擎
查询执行引擎会根据优化阶段生成的执行计划(一棵指令树),依次执行并给出结果。主要实现方式是通过调用存储引擎的API实现,通过叠加等操作实现查询。
6、响应给客户端
无论是否有查询结果,都会返回给客户端,包括影响到行数、执行时长等。
此时若查询缓存打开,会将查询结果存入缓存。
当有查询结果时,将结果集返回是一个增量过程。mysql可能在生成的第一条结果时就会将结果返回给客户端,客户端不断接收直至完毕。服务端无需存储结果集占用内存,客户端也可以第一时间接收到结果。
物理存储结构
日志文件
-
错误日志
-
二进制日志
-
通用查询日志
-
慢查询日志
-
事务日志:重做日志redo log、回滚日志undo log
redo log通常是物理日志,记录的是数据页的物理修改,用来恢复提交后的物理数据页(只能恢复到最后一次提交的位置)。
undo log一般是逻辑日志,根据每行记录进行记录,用来回滚行记录到某个版本。
-
中继日志
数据文件
InnoDB数据文件
MyISAM数据文件
本文来自博客园,作者:白芷呀,转载请注明原文链接:https://www.cnblogs.com/angelica-duhurica/p/11303253.html