假如想深化地学习 MySQL ,那么应该从宏观的架构上面着手,这一篇咱们学习 MySQL 的全体架构及句子履行流程之 Server 层

MySQL 全体架构

全体上来说 MySQL 服务端能够分红两层

  • Server 层:担任 SQL 句子层面的处理,解析、优化等
  • 存储引擎层:担任数据的存储与读取,不同的存储引擎有不同的数据存储与查询的手法,存储引擎层给 Server 层提供了统一的接口拜访数据

MySQL Server 层架构图

MySQL 语句执行流程- Server 层

衔接处理器

衔接处理器首要处理客户端的衔接是否正确,是否具有相应数据操作的权限

解析器

解析器的作用是对客户端传来的 SQL 句子进行以下作业:

  • 语法解析:检查 SQL 句子的语法,括号、引号是否闭合等
  • 词法解析:把 SQL 句子中的关键词、表名、字段名拆分红一个个节点,终究得到一颗解析树

MySQL 语句执行流程- Server 层

预处理器

解析器首要是检查语法词法方面,可是假如语法词法都正确,可是表、字段是不存在的,那么这段 SQL 句子也是无法正确履行的。

所以预处理器的作用是:语义解析判别解析树的语义是否正确,表、字段这些是否存在,预处理后会得到一颗新的解析树。

查询优化器

查询优化器结构

MySQL 语句执行流程- Server 层

在 MySQL 中一条 SQL 句子的履行方法有多种,尽管终究都会得到相同的成果,可是存在开支上的差异,详细挑选哪一种履行方法是由查询优化器来决议的。比方说:

  • 表中有多个索引能够挑选,详细挑选哪一个索引
  • 当咱们对多张表进行相关查询时,以哪一张表的数据为基准表

查询优化器是依据开支(cost)的优化器,它的作业原理是依据解析树生成的多种履行计划,会评价各种履行方法所需的开支(cost),终究会得到一个开支最小的履行计划作为终究方案

可是这个开支最小的履行方法不一定是最优的履行方法,比方本该运用索引,却进行了全表扫描等。尽管查询优化器中有「优化」两个字,可是这个优化并不是万能的,许多时分愈加需要考虑 SQL 句子书写得是否合理。

逻辑查询优化

逻辑查询优化首要担任进行一些联系代数对 SQL 句子进行优化,从而使 SQL 句子履行功率更高

逻辑查询优化咱们能够运用几个案例来简略理解

  • 子查询兼并

    兼并前

    SELECT * FROM t1 WHERE a1<10 AND (
     EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=1) OR
     EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=2)
    );
    

    兼并后

    SELECT * FROM t1 WHERE a1<10 AND (
     EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND (t2.b2=1 OR t2.b2=2)
    );
    

    把多个子查询通过兼并查询条件而兼并查询,把多次衔接操作削减为单次表扫描和单次衔接

  • 等价谓词重写

    像咱们熟悉的 like 模糊查询,% 写在条件后边才会进行索引规模查询,其实这是查询优化器的劳绩

    假定运用的条件都是有树立索引的,重写前

    SELECT * FROM USERINFO WHERE name LIKE 'Abc%';
    

    重写后

    SELECT * FROM USERINFO WHERE name >= 'Abc' AND name < 'Abd';
    

    这便是为什么能进行索引规模查询的答案

  • 条件简化

    条件简化也是利用一些等式、代数联系来完成简化

    • 去除表达式中的冗余括号,削减语法分析时发生的AND和OR 树的层 次,比方 ((a AND b) AND (c AND d)) 简化为 a AND b AND c AND d
    • 常量传递,比方 col1 = col2 AND col2 = 3 简化为 col1 = 3 AND col2 = 3
    • 表达式计算,关于一些可直接求解的表达式会转换为终究的计算成果,比方 col1 = 1+2 简化为 col1 = 3

物理查询优化

物理查询优化首要做的作业是依据 SQL 句子分别对多种履行计划进行开支的评价

物理查询优化首要处理以下几个问题:

  1. 单表扫描中采用哪种方法是开支最小的(扫描索引+回表 or 全表扫描)
  2. 存在表衔接的时分运用哪种衔接方法是开支最小的

简略了解一下价值评价,价值评价是依据 CPU 价值和 IO 价值两个维度的

扫描方法 价值评价公式
次序扫描 N_page * a_page_IO_time + N_tuple * a_tuple_CPU_time
索引扫描 C_index + N_page_index * a_page_IO_time

上述参数说明如下:

  • a_page_IO_time, 一个数据页加载的IO耗时
  • N_page,数据页数量
  • N_tuple,元组数(元组理解为一行数据)
  • a_tuple_CPU_time,一个元组从数据页中解析的CPU耗时
  • C_index,索引的IO耗时
  • N_page_index,索引页数量

关于索引成本计算能够参考这篇文章:MySQL查询为什么挑选运用这个索引?——依据MySQL 8.0.22索引成本计算

履行计划

履行计划是查询优化器的产物,终究会交给存储引擎进行履行。履行计划能够协助咱们得知 MySQL 会怎样履行这条 SQL 句子。

运用 explain 关键字检查 SQL 句子的履行计划,能够得到以下信息:

  • id:嵌套查询中查询的履行次序
  • possible_keys:本次查询可能用到的索引
  • key:实际用到的索引
  • key_len:运用到的索引的字段长度
  • rows:得到成果大概要检索多少行数据
  • select_type多表之间的衔接类型
  • extra:额外的信息,是否有索引掩盖、索引下推等

履行器与存储引擎

履行期担任拿着查询优化器生成的履行计划,对存储引擎调用统一的数据操作接口。

MySQL 服务端规则了数据怎么存储、怎么提取、怎么更新的规范,这个规范由存储引擎来完成,不同的存储引擎的完成方法不同,所以不同的存储引擎会呈现其共同的功用和特色。其中最常用的存储引擎是 InnoDB 和 MyISAM ,简略说说这两款存储引擎的特色

InnoDB:

  • 支撑外键、业务,确保了数据的完整性和一致性
  • 支撑更细的锁粒度,对锁的控制更好,读写功率更高

MyISAM

  • 不支撑业务,只支撑行锁,适合数据只读的场景

存储引擎方面暂时先不翻开,会在其他文章持续交叉他们的比照,以及会详细分析 InnoDB 更新数据的流程

Binlog

Binlog 是 MySQL Server 层自己保护的一个二进制日志,以事件的形式记载了所有 DDL 和 DML 句子

  • 日志写入的机制是次序写,省去寻址时间,写入功率高
  • 日志采用追加写的模式,一份日志文件写到一定大小会切换到下一个

Binlog 中最重要的功用:数据康复与主从同步

  • 数据康复:因为 Binlog 记载了 DDL 和 DML 句子,能够通过 mysqlbinlog 东西来康复数据
  • 主从同步:master 结点把它的 Binlog 传递给 slave 结点,slave 依据 master 中发生过的数据修改同步修改到自己库上

Binlog 开启后会有性能上的消耗,默认是封闭的,假如需要翻开的话需要在 MySQL 装备文件 my.cnf 中的mysqld 区加入以下装备

[mysqld]
log-bin=/data/mysql-bin #日志路径
binlog_format=MIXED

Binlog 相关查询指令

-- 检查 Binlog 的开关状态、文件目录、索引文件目录等信息
show variables like '%log_bin%';
-- 检查 Binlog 文件信息
show binary logs;

Binlog 格局

  • row:记载数据被修改成什么姿态。可是无法记载函数履行的成果,而且假如一条修改句子修改了大量的数据行或者 alter table 时,那么日志量会很大
  • statement:记载履行了的 SQL 句子。削减 Binlog 日志量,节约 IO,可是可能会呈现同一条 SQL 句子在 master 结点和 slave 结点上成果不一致的状况
  • mixed:以上两种格局混合运用,MySQL 依据 SQL 句子自己挑选最优的

MySQL 在业务提交时需要写入 Binlog,这一点在介绍存储引擎层时再详细地介绍

总结

从前,只知道在客户端软件上写下 SQL 句子,点击履行,拿到数据

到现在终于了解到一条查询句子传入 MySQL 服务端后需要阅历这一系列的操作

  1. 解析器依据这条 SQL 句子的语法、词法进行检查,假如没有过错的话会按关键词拆分红一个个节点,终究构成一棵解析树
  2. 预处理器会检查 SQL 句子的语义,检查 SQL 句子是否有歧义、字段等是否存在,构成一棵新的解析树
  3. 查询优化器拿到这个解析树生成的各种履行计划,通过逻辑查询优化、物理查询优化后得到一个开支最小的履行计划
  4. 履行器拿到这份履行计划调用存储引擎的接口
  5. 存储引擎依据履行计划进行数据查询,查询会查询调用操作体系中文件体系的一些接口,完成数据查询,最终回来给客户端

以上便是 SQL 句子在 MySQL 的 Server 层流转的全体流程。

假如这篇文章对你有协助,请给我一个免费的大拇哥

我的个人知识库 GitHub 地址:github.com/gelald/javr… 请给我 star 支撑一下,谢谢~