文章目录
执行一条select语句,期间发生了什么
MySQL执行流程
-
server层负责建立连接、分析和执行SQL
- 包括连接器、查询缓存、解析器、预处理器、优化器、执行器等,所有内置函数和所有跨存储引擎的功能在该层实现
-
存储引擎层负责数据的存储和提取
-
索引数据结构就是由存储引擎层实现,不同的存储引擎支持的索引类型也不相同
-
InnoDB支持索引类型是B+树,默认使用
-
在数据表中创建的主键索引和二级索引默认使用B+树索引
-
-
第一步:连接器
markdown
连接mysql服务器
linux: mysql -h ip地址 -u 用户名 -p 密码
mysql基于TCP协议进行传输,需要三次握手
与客户端TCP三次握手建立连接 => 验证用户名、密码 => 连接器获取该用户权限(若管理员中途修改权限也不起效,需要新建连接才会使用新的权限设置)
如何查看 MySQL 服务被多少个客户端连接了?
show processlist
若用户的Command列状态为Sleep则说明这是一个空闲的连接
空闲连接会一直占用着吗?
markdown不会,mysql定义了空闲连接的最大空闲时长,由wait_timeout参数控制,超过这个时间,连接器自动将它断开 1. 查看最大空闲时长 show variables like 'wait_timeout' 2. 手动断开空闲连接 kill connection+id
一个处于空闲状态的连接被服务端断开后,客户端不会马上知道,等客户端发起下一个请求才会收到报错
MySQL的连接数有限制吗?
有,由max_connections控制
MySQL的长连接 vs. 短连接
markdown短连接: 连接mysql服务 执行mysql 断开 长连接: 连接mysql 执行mysql 执行 执行 执行 .... 断开
使用长连接可以减少建立连接和断开连接的过程(推荐) 缺点:占用内存增多
怎么结局长连接占用内存的问题?
markdown1. 定期断开长连接 2. 客户端主动重置连接
第二步:查询缓存
连接器完成工作后,客户端可以向mysql服务发送sql语句,mysql服务收到sql语句后,就会解析处sql语句的第一个字段,查看是什么类型的语句
select语句 => 在查询缓存里查找缓存数据(key-value形式存储,key:sql语句,value:查询结果) => 若命中,则直接返回value给客户端;若未命中,继续执行,执行完后查询结果存入查询缓存
缺点:对于更新频繁的表,只要一个表有更新操作,那么这个表的查询缓存就会被清空
mysql8.0开始删除查询缓存
第三步:解析SQL
解析器完成
- 词法分析
关键字 | 非关键字 | 关键字 | 非关键字 |
---|---|---|---|
select | username | from | userinfo |
- 语法分析
根据语法规则,判断sql语句是否正确,若正确则构建SQL语法树,否则报错。
注意: 表不存在或字段不存在,不是解析器里做的(预处理器负责),解析器只负责检查语法和构建语法树
第四步:执行SQL
预处理阶段 => 优化阶段 => 执行阶段
- 预处理器
- 检查SQL查询语句中的表或字段是否存在(不存在则报错)
- 将select * 中的 * 符号扩展为表上所有列
- 优化器
为sql查询语句制定一个执行计划
优化器主要负责将sql查询语句的执行方案确定下来,表中有多个索引时,选择使用哪个索引
查看优化器使用了哪个索引
explain sql查询语句 (输出这条sql语句的执行计划)
查看执行计划的key
PRIMARY 主键索引
NULL 没有使用索引,全表扫描
例:覆盖索引
直接在二级索引就能查找到结果(因为二级索引的 B+ 树的叶子节点的数据存储的是主键值,就没必要在主键索引查找了,因为查询主键索引的 B+ 树的成本会比查询二级索引的 B+ 的成本大)
select id from product where id > 1 and name like 'i%' extra为Using index,表明使用了覆盖索引优化
- 执行器
执行器与存储引擎进行交互,从存储引擎读取记录,返回给客户端
- 主键索引查询(存储引擎定位符合条件的第一条记录)
- 全表扫描(存储引擎读取表中第一条记录)
- 索引下推