一条 SQL 的执行流程

一条查询的语句是如何执行的?

MySQL的逻辑架构图,基于5.7版本,8.0的版本去除了查询缓存。

大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。

Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5版本开始成为了默认存储引擎。

也就是说,你执行 create table 建表的时候,如果不指定引擎类型,默认使用的就是 InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在 create table 语句中使用engine=memory来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同,支持的功能也不同。

一条 SQL 的执行流程_第1张图片

以下从5步进行说明一条 SQL 的执行流程。

我们的程序或者工具要操作数据库,第一步要做什么事情?

跟数据库建立连接。

一、连接

作用:管理连接,权限验证

MySQL服务监听的端口默认是3306,客户端连接服务端的方式有很多。

可以是同步的也可以是异步的,可以是长连接也可以是短连接,可以是 TCP 也可以是 Unix Socket, MySQL 有专门处理连接的模块,连接的时候需要验证权限。

我们怎么查看MySQL当前有多少个连接?

可以用show status命令,模糊匹配Thread

show global status like 'Thread%';
字段 含义
Threads cached 缓存中的线程连接数。.
Threads connected 当前打开的连接数。
Threads created 为处理连接创建的线程数。
Threads running 非睡眠状态的连接数,通常指并发连接数:
Threadpool_idle_threads 线程池空闲线程,8.0中有。
Threadpool_threads 线程池,8.0中有。
问题:为什么连接数是查看线程?客户端的连接和服务端的线程有什么关系?

客户端每产生一个连接或者一个会话,在服务端就会创建一个线程来处理。反过来, 如果要杀死会话,就是Kill线程。

既然是分配线程的话,保持连接肯定会消耗服务端的资源。MySQL 会把那些长时间 不活动的(SLEEP)连接自动断开。

二、查询缓存

  • 默认关闭不推荐使用,SQL语句必须一 模一样,中间多一个空格,字母大小写不同都被认为是不同的的SQL。
  • 表里面任何一条数据发生变化的时候,这张表所有缓存都会失效,所以对 于有大量数据更新的应用,也不适合。
  • MySQL 8.0中,查询缓存已经被移除了。

三、分析器-语法解析和预处理(Parser & Preprocessor)

这一步主要做的事情是对语句基于SQL语法进行词法和语法分析和语义的解析。

3.1 词法解析

词法分析就是把一个完整的SQL语句打碎成一个个的单词。

比如一个简单的SQL语句:

select name from user where id = 1;

它会打碎成8个符号,每个符号是什么类型,从哪里开始到哪里结束。

3.2 语法解析

语法分析会对SQL做一些语法检查,比如单引号有没有闭合, 然后根据MySQL定义的语法规则,根据SQL语句生成一个数据结构。

这个数据结构我 们把它叫做解析树(select lex)。
一条 SQL 的执行流程_第2张图片

3.3 预处理器

问题:如果我写了一个词法和语法都正确的SQL,但是表名或者字段不存在,会在 哪里报错?是在数据库的执行层还是解析器?比如:

select * from aaaaa;

似乎解析器可以分析语法,但是它怎么知道数据库里面有什么表,表里面有什么字段呢?

实际上还是在解析的时候报错,解析 SQL 的环节里面有个预处理器

它会检査生成的解析树,解决解析器无法解析的语义。比如,它会检査表和列名是否存在,检査名字和别名,保证没有歧义。

预处理之后得到一个新的解析树。

四、查询优化(Query Optimizer)与查询执行计划

作用:生成、选择执行路径,索引的选择,Cost(计算成本最低的)

査询优化器的目的就是根据解析树生成不同的执行计划Execution Plan,然后选 择一种最优的执行计划,MySQL里面使用的是基于开销cost的优化器,那种执行计划开销最小,就用哪种。

MySQL的优化器能处理哪些优化类型
  • 当我们对多张表进行关联查询的时候,以哪个表的数据作为基准表。
  • 有多个索弓|可以使用的时候,选择哪个索引。

但是优化器也不是万能的,并不是再垃圾的SQL语句都能自动优化,也不是每次都能选择到最优的执行计划,大家在编写SQL语句的时候还是要注意。

优化完之后,得到一个什么东西呢?优化器最终会把解析树变成一个査询执行计划。查询执行计划是一个数据结构。

在SQL语句前面加上EXPLAIN,就可以看到执行计划的信息。
EXPLAIN select name fiom user where id=l;

如果要得到详细的信息,还可以用FORMAT=JSON,或者开启optimizer traceo

-- 会得到一个json数据
EXPLAIN FORMAT=JSON select * from card;

五、存储引擎

得到执行计划以后,SQL 语句是不是终于可以执行了?

首选要选择存储引擎,利用存储引擎提供的相应的API来完成操作,最后把数据返回给客户端。

不同的存储引擎存放数据的方式不一样,产生的文件也不一样,innodb是1个, memory没有,myisam 是两个。

5.1 存储引擎选择

没有指定的时候,数据库就会使用默认的存储引擎,5.5.5之前,默认的存储引擎是MylSAM, 5.5.5之后,默认的存储引擎是 InnoDB。

5.2 存储引擎比较

MylSAM (3个文件):应用范围比较小。表级锁定限制了读/写的性能,因此在Web和数据仓库配置中,它通常用于只读或以读为主的工作。

特点:

  • 支持表级别的锁(插入和更新会锁表)。不支持事务。
  • 拥有较高的插入(insert)和查询(select)速度。
  • 存储了表的行数(count速度更快)。

(怎么快速向数据库插入100万条数据?我们有一种先用 MylSAM 插入数据,然后修改存储引擎为 InnoDB 的操作。)

适合:只读之类的数据分析的项目。

InnoDB (2个文件)

mysql 5.7中的默认存储引擎。InnoDB 是一个事务安全(与ACID兼容)的MySQL 存储引擎,它具有提交、回滚和崩溃恢复功能来保护用户数据。InnoDB 行级锁(不升级 为更粗粒度的锁)和 Oracle 风格的一致非锁读提高了多用户并发性和性能。InnoDB 将 用户数据存储在聚集索引中,以减少基于主键的常见查询的I/O。为了保持数据完整性, InnoDB 还支持外键引用完整性约束。

特点:

  • 支持事务,支持外键,因此数据的完整性、一致性更高。
  • 支持行级别的锁和表级别的锁。
  • 支持读写并发,写不阻塞读(MVCC)。
  • 特殊的索引存放方式,可以减少I。,提升査询效率。

适合:经常更新的表,存在并发读写或者有事务处理的业务系统。

Memory (1个文件)

将所有数据存储在RAM中,以便在需要快速查找非关键数据的环境中快速访问。这 个引擎以前被称为堆引擎。其使用案例正在减少;InnoDB及其缓冲池内存区域提供了一 种通用、持久的方法来将大部分或所有数据保存在内存中,而 ndbduster 为大型分布式 数据集提供了快速的键值查找。

特点:

  • 把数据放在内存里面,读写的速度很快,但是数据库重启或者崩溃,数据会全部消 失。只适合做临时表。
  • 将表中的数据存储到内存中。

不同的存储引擎提供的特性都 不一样,它们有不同的存储机制、索引方式、锁定水平等功能。

5.3 如何选择存储引擎?
  • 如果对数据一致性要求比较高,需要事务支持,可以选择 InnoDB。
  • 如果数据查询多更新少,对查询性能要求比较高,可以选择 My ISAM。
  • 如果需要一个用于查询的临时表,可以选择 Memory。

你可能感兴趣的:(MySQL,mysql,数据库)