一条查询的语句是如何执行的?
MySQL的逻辑架构图,基于5.7版本,8.0的版本去除了查询缓存。
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。
Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5版本开始成为了默认存储引擎。
也就是说,你执行 create table 建表的时候,如果不指定引擎类型,默认使用的就是 InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在 create table 语句中使用engine=memory
来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同,支持的功能也不同。
以下从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语句生成一个数据结构。
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。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68381.html