MySQL学习笔记:一条SQL语句的执行过程

MySQL数据库的组成

如图所示,MySQL由Server层和存储引擎层两部分组成:
MySQL学习笔记:一条SQL语句的执行过程_第1张图片

Server层

Sever层包括连接器、查询缓存、分析器、优化器、执行器等,主要参与数据库连接、SQL解析执行;所有的内置函数,如日期、时间、数学和加密函数等、所有跨存储引擎的功能,如存储过程、触发器、视图等也都是在该层实现的。

存储引擎层

存储引擎层主要负责数据的存取,常见存储引擎包括InnoDB、MyISaM、Memory等,InnoDB是现在MySQL默认的存储引擎。

一条SQL语句的执行

以 select * from T where k=1 为例

连接器

顾名思义,连接器负责数据库的连接,校验身份、保持客户端与MySQL的连接就是它的责任。
使用如下命令建立连接:

mysql -h$ip -P$port -u$user -p

输入完用户名与密码之后,连接器会校验是否匹配,若登陆成功则查找用户对应的权限,之后通过该连接做的所有查询都是基于此权限,这也意味着一旦连接建立,即使用户权限被更改,也不会影响已建立连接的查询。
连接建立后若8小时没用相关操作连接器就会自动断开该连接,8小时可以通过参数wait_timeout控制。
数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
连接过程是使用TCP协议的,所以为了性能应该尽量减少建立连接的动作,即尽量多使用长连接。
长连接实际上是一种空间换时间的做法,因为MySQL临时使用的内存是管理在连接对象里面的,长连接如果持续累计下来可能导致内存占用太大,导致MySQL异常重启。

查询缓存

连接建立完成后,你就可以执行 select 语句了。执行逻辑就会来到第二步:查询缓存。
对于查询过的SQL语句,MySQL会将结果以Key-Value的形式保存下来,如果新来的查询命中了缓存,则会直接返回结果,效率很高。
但是在MySQL8.0查询缓存已经被彻底抛弃掉了,因为通常情况下,查询缓存的失效特别频繁(某个表有更新,该表的所有查询缓存都会清空),命中率极低。

分析器

如果没有某种查询缓存,就需要真正执行SQL语句了,分析器首先会做词法分析,将SQL语句转换为类似“抽象语法树(AST)”的结构,明白字符串中各个字符分别代表什么,做完了词法分析,就会进行语法分析的步骤,可以理解成鉴别词法分析的“词”以语句的方式组合是否会有问题。值得注意的是,语法分析是能够读取到表的信息的(列名,而非具体数据),所以关于字段名是否存在也是在该步骤校验的。

优化器

通过了语法分析,MySQL还会将当前的语句执行步骤做优化,例如:
select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20。
也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。
优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。

执行器

开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。
校验权限通过后,执行器会调用存储引擎接口去取T表的第一行,判断 k 是否为1,如果是则将该行保存在结果集中,然后调用引擎接口取“下一行”,重复上述判断逻辑,直到遍历完整个表。
对于有索引的表,执行的逻辑也大同小异,无非是索引能够使得查询更加高效,可以避免一些无意义的遍历。
在数据库的慢查询日志中有一个 rows_examined 字段,该字段代表语句执行过程中扫描了多少行,但在有些场景下,执行器调用一次,内部引擎同时会扫描多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的

参考资料
极客时间《MySQL实战45讲》 01

你可能感兴趣的:(MySQL学习笔记,mysql,sql,数据库)