MySQL的架构
MySQL架构分为server层和存储引擎层
server层负责建立连接、分析和执行SQL。还会实现一些内置函数和跨存储引擎的功能(存储过程、触发器、视图等)
存储引擎层负责实现索引数据结构,不同的存储引擎支持的索引类型不同,InnoDB支持的索引类型是B+树
select具体执行流程
1.连接器
MySQL客户端通过TCP与MySQL服务端建立连接,并通过连接器验证用户名、密码是否正确,并拿到该用户的权限,之后的权限逻辑判断都基于此时读到的权限。也就是如果一个用户已经建立了连接,即使管理员中途修改了该用户的权限,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。
- 长连接与短连接
长连接:客户端与服务端建立连接后,执行较多的SQL操作后才断开。虽然使得不会频繁地断开连接和建立连接,但是却因为长期使用一个连接对象而占用内存资源??
短连接:客户端与服务端建立连接后,执行少数的SQL操作后便断开
- 如何解决长连接造成的内存资源浪费?
- 定期断开长连接
- 客户端主动重置连接,释放内存
mysql> mysql_reset_connection()
2.查询缓存
在MySQL8.0之前,执行SQL语句的时候,MySQL会先解析SQL语句的第一个字段,如果发现是select查询语句,则会先去查询缓存中查找是否有这题查询语句,查询缓存相当于一个map,k是查询语句,v是查询结果,如果有这个k,则直接返回v。但是查询缓存很鸡肋,因为每执行一条更新语句,查询缓存就会被清空,如果执行了一个大的查询操作,查询缓存中保存了很多记录,但是接着因为一条更新语句这些查询缓存还没来得及用就被清空了。
因此,MySQL8.0之后执行一条查询语句,就不会再走查询缓存了
Tip:需要注意的是,这里说的查询缓存是server层的,和InnoDB存储引擎中的buffer pool不一样
3.解析SQL
两个部分:词法分析和语法分析
- 词法分析就是看看SQL语句中有哪些关键字,然后构建语法树,方便后面获取SQL类型、表名、字段名、where条件等
- 语法分析就是判断看看满不满足MySQL的语法规范
Tip:解析器不会去判断字段或者表存不存在
4.执行SQL
又具体分为三步:
- prepare预处理阶段(预处理器)
在这个节点会判断要查询的表是否存在,并将select 中的扩展为表上所有的列
- optimize优化阶段(优化器)
确定SQL语句的最优执行方案,也就是查询成本最小的方案。
比如现在我们id是主键索引,name是二级索引,我们执行以下查询语句
select id from product where id > 1 and name like 'i%';
优化器发现既可以走主键索引,也可以走二级索引,但是因为我们只需要查询id,所以我们可以直接走二级索引,这样可以覆盖索引,也就是不需要回表操作(去主键索引中查找),减少了查询的成本
- execute执行阶段(执行器)
这部分主要是执行器会和存储引擎进行交互,通过优化器的执行方案,调用存储引擎的对应接口可能是全扫描的接口或者是索引查询的接口
全表扫描的情况下,server层的执行器调用全扫描的接口,存储引擎会去读取表中的第一条记录给执行器(server层)判断是否满足查询条件,满足则直接返回给客户端。如此循环操作,直到存储引擎将表中的数据读取完
如果是索引查询,又分为主键索引和二级索引
主键索引的情况下,server层的执行器调用索引查询的接口,存储引擎会去定位符合主键查询条件的第一条记录,然后返回给执行器,执行器判断是否符合查询的条件,符合则直接返回给客户端。如此循环操作,直到存储引擎将表中的数据读取完
二级索引的情况下,其实和主键索引查询过程差不多。值得注意的是这里面有个索引下推的操作,使得回表操作大大减少。
- 索引下推
假设在有(age,reward)联合二级索引的情况下,执行下面的SQL语句
select * from t_user where age > 20 and reward = 100000;
这时因为出现了>号,则只有age字段的二级索引生效
在MySQL5.6之前,不使用索引下推,则在存储引擎在定位到一条记录后就会根据主键直接进行回表操作,再将查询结果交给server层(执行器),server层再判断是否满足二级索引失效的字段对应的查询条件,是再返回给客户端
而在MySQL5.6后,存储引擎在定位到一条记录后不会直接进行回表操作,而是先判断是否满足二级索引失效的字段对应的查询条件,不满足则跳过,满足再进行回表操作,并将查询到的结果返回给server层…