第04章 逻辑架构【1.MySQL架构篇】【MySQL高级】2

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 第04章 逻辑架构【1.MySQL架构篇】【MySQL高级】2

2. 解析器:在解析器中对 SQL 语句进行语法分析、语义分析。

如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL需要知道你要做什么,因此需要对SQL语句做解析。SQL语句的分析分为词法分析与语法分析。

分析器先做“ 词法分析 ”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。 MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。


接着,要做“ 语法分析 ”。根据词法分析的结果,语法分析器(比如:Bison)会根据语法规则,判断你输入的这个 SQL 语句是否 满足 MySQL 语法 。

#语法错误:group by后面没有job_id(词对但是组合在一起出现了问题)
select department_id,job_id,avg(salary) from employees group by department_id;

如果你的语句不对,就会收到"You have an error in your SQL syntax"的错误提醒,比如语句from写成了"rom"–>词法错误。

# 语句
mysql> select *fro test where id=1;
# 错误
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'fro test where id=1' at line 1
mysql> 

如果SQL语句正确,则会生成一个这样的语法树:


下面是SQL词法分析的过程步骤:


至此解析器的工作结束,接下来进入到优化器。

3.优化器:在优化器中会确定 SQL 语句的执行路径,比如是根据全表检索 ,还是根据索引检索等。

经过了解析器,MySQL就知道你要做什么了。在开始执行之前,还要先经过优化器的处理一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。


比如:优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序,还有表达式简化、子查询转为连接、外连接转为内连接等。

举例:如下语句是执行两个表的 join:

select * from test1 join test2 using(ID)
where test1.name='zhangwei' and test2.name='mysql高级课程';
方案1:可以先从表 test1 里面取出 name='zhangwei’的记录的 ID 值,再根据 ID 值
关联到表test2,再判断test2 里面 name的值是否等于 ‘mysql高级课程’。
方案2:可以先从表 test2 里面取出 name=‘mysql高级课程’ 的记录的 ID 值,
再根据 ID 值关联到 test1,再判断 test1 里面 name的值是否等于 zhangwei。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择
使用哪一个方案。优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。
如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等。后面讲到索引我们再谈。

在查询优化器中,可以分为逻辑查询 优化阶段和物理查询优化阶段。


逻辑查询优化就是通过改变SQL语句的内容来使得SQL查询更高效,同时为物理查询优化提供更多的候选执行计划。通常采用的方式是对SQL语句进行等价变换,对查询进行重写,而查询重写的数学基础就是关系代数。对条件表达式进行等价谓词重写、条件简化,对视图进行重写,对子查询进行优化,对连接语义进行了外连接消除、嵌套连接消除等。


物理查询优化是基于关系代数进行的查询重写,而关系代数的每一步都对应着物理计算,这些物理计算往往存在多种算法。因此需要计算各种物理路径的代价,从中选择代价最小的作为执行计划。在这个阶段里,对于单表和多表连接的操作,需要高效地使用索引,提升直询效率。

4. 执行器:

截止到现在,还没有真正去读写真实的表,仅仅只是产出了一个执行计划。于是就进入了执行器阶段


在执行之前需要判断该用户是否具备权限 。如果没有,就会返回权限错误。如果具备权限,就执行 SQL查询并返回结果。在 MySQL8.0 以下的版本,如果设置了查询缓存,这时会将查询结果进行缓存。

select * from test where id=1;

如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,调用存储引擎API对表进行的读写。存储引擎API只是抽象接口,下面还有个存储引擎层,具体实现还是要看表选择的存储引擎。


比如:表 test 中,ID 字段没有索引,那么执行器的执行流程是这样的:

调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是1,如果不是则跳过,如果是则将这行存在结果集中;
调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。

至此,这个语句就执行完成了。对于有索引的表,执行的逻辑也差不多。

SQL 语句在 MySQL 中的流程是: SQL语句→查询缓存→解析器→优化器→执行器



2.2 MySQL8中SQL执行原理

前面的结构图很复杂,我们需要抓取最核心的部分:SQL的执行原理。不同的DBMS的SQL的执行原理是相通的,只是在不同的软件中,各有各的实现路径。
既然一条SQL语句会经历不同的模块,那我们就来看下,在不同的模块中。SQL执行所使用的资源(时间)是怎样的。如何在MySQL中对一条 SQL语句的执行时间进行分析。

1.确认profiling 是否开启

了解查询语句底层执行的过程: select @@profiling;或者show variables like '%profiling%'查看是否开启计划。开启它可以让MySQL收集在SQL执行时所使用的资源情况,命令如下:

select @@profiling;
/*
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
*/
show variables like 'profiling';
/*
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| profiling     | OFF   |
+---------------+-------+
*/


profiling=0 代表关闭,我们需要把 profiling 打开,即设置为 1:

set profiling=1;
select @@profiling;
/*
+-------------+
| @@profiling |
+-------------+
|           1 |
+-------------+
*/

Profiling功能由MySQL会话变量:profiling控制。默认是OFF(关闭状态)

2.多次执行相同SQL查询

然后我们执行一个 SQL 查询(你可以执行任何一个 SQL 查询):

select * from employees;

3.查看profiles

show profiles和show profile语句可以展示当前会话(退出session后,profling重置为o)中执行语句的资源使用情况。

查看当前会话所产生的所有 profiles:

show profiles; # 显示最近的几次查询
/*本机输出:
+----------+------------+-------------------------+
| Query_ID | Duration   | Query                   |
+----------+------------+-------------------------+
|        1 | 0.00031625 | select @@profiling      |
|        2 | 0.00019625 | select * from employees |
+----------+------------+-------------------------+
*/



4.查看profile

显示执行计划,查看程序的执行步骤:

默认是最近的一次


当然你也可以查询指定的 Query ID,比如:

show profile for query 7;

show profile cpu,block io for query 6;


可以看出都是17条,所以是间接证明8.0是没有开启缓存的

1、除了查看cpu、io阻塞等参数情况,还可以查询下列参数的利用情况。

Syntax :
SHOW PROFILE [type [,type] ... ]
[ FOR QUERY n]
[LIMIT row_count [OFFSET offset]]
type : {
ALL --显示所有参数的开销信息
BLOCK IO --显示IO的相关开销
CONTEXT SWITCHES -- 上下文切换和关开信息
CPU --显示CPU的相关开销
IPC --显示发送和接收相关开销信息
MEMORY --显示内存相关开销信息
PAGE FAULTS -- 显示页面错读和关开销信息
SOURCE -- 显示和Saurce_function, Source_file , Source_line 相关的开销信息
SWAPS -- 显示交换次数相关的开销信息
}



2.3 MySQL5.7中SQL执行原理

上述操作在MySQL5.7中测试,发现前后两次相同的sql语句,执行的查询过程仍然是相同的。不是会使用缓存吗?这里我们需要显式开启查询缓存模式 。
在MySQL5.7中如下设置:

1.配置文件中开启查询缓存

在 /etc/my.cnf 中新增一行:

query_cache_type=1

2.重启mysql服务

systemctl restart mysqld

3.开启查询执行计划

由于重启过服务,需要重新执行如下指令,开启profiling。

set profiling=1;

4.执行语句两次:

select * from departments;
select * from departments;

5.查看profiles

6.查看profile

显示执行计划,查看程序的执行步骤:

show profile for query 7;

show profile for query 8;


结论不言而喻。执行编号8时,比执行编号7时少了很多信息,可以看出查询语句直接从缓存中获取数据。

  • 注意1:
 SQL必须是一致的,否则,不能命中缓存。

例如:

#虽然查询结果一致。但并没有命中缓存
select * from mydb.mytbl where id=2
select * from mydb.mytbl where id>1 and id<3
  • 注意2:
    同样的开启缓存的配置信息query_cache_type=1如果在MySQL8中添加。重启服务时会报错:
[ root@atguigue1 ~]# vim /etc/my . cnf
[ root@atguigu01 ~]# systemctl restart mysqld ;
Job for mysqld.service failed because the control process exited with error code. See"systemctl status mysqld.service" and "journalctl -xe" for details.

分别在MySQL5.7和 MySQL8中执行如下命令:

mysql> show variables like ' %query_cache%' ;
  • MysQL5.7中显示:

    MysQL8.0中显示:


2.4 SQL语法顺序

随着Mysql版本的更新换代,其优化器也在不断的升级,优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。

需求:查询每个部门年龄高于20岁的人数且高于20岁人数不能少于2人,显示人数最多的第一名部门信息下面是经常出现的查询顺序:

下面是经常出现的查询顺序:


2.5 Oracle中的SQL执行流程(了解)

Oracle 中采用了共享池来判断 SQL 语句是否存在缓存和执行计划,通过这一步骤我们可以知道应该采用硬解析还是软解析。

我们先来看下 SQL 在 Oracle 中的执行过程:

从上面这张图中可以看出,SQL 语句在 Oracle 中经历了以下的几个步骤。

1.语法检查:检查 SQL 拼写是否正确,如果不正确,Oracle 会报语法错误。
2.语义检查:检查 SQL 中的访问对象是否存在。比如我们在写 SELECT 语句的时候,列名写错了,系统就会提示错误。语法检查和语义检查的作用是保证 SQL 语句没有错误。
3.权限检查:看用户是否具备访问该数据的权限。
4.共享池检查:共享池(Shared Pool)是一块内存池,最主要的作用是缓存 SQL 语句和该语句的执行计划。Oracle 通过检查共享池是否存在 SQL 语句的执行计划,来判断进行软解析,还是硬解析。那软解析和硬解析又该怎么理解呢?
在共享池中,Oracle 首先对 SQL 语句进行 Hash 运算 ,然后根据 Hash 值在库缓存(Library Cache)中查找,如果存在 SQL 语句的执行计划 ,就直接拿来执行,直接进入“执行器”的环节,这就是 软解析 。


如果没有找到 SQL 语句和执行计划,Oracle 就需要创建解析树进行解析,生成执行计划,进入“优化器”这个步骤,这就是硬解析 。

5.优化器:优化器中就是要进行硬解析,也就是决定怎么做,比如创建解析树,生成执行计划。

.

6.执行器:当有了解析树和执行计划之后,就知道了 SQL 该怎么被执行,这样就可以在执行器中执行语句了。

共享池是 Oracle 中的术语,包括了库缓存,数据字典缓冲区等。我们上面已经讲到了库缓存区,它主要缓存 SQL 语句和执行计划。而 数据字典缓冲区 存储的是 Oracle 中的对象定义,比如表、视图、索引等对象。当对 SQL 语句进行解析的时候,如果需要相关的数据,会从数据字典缓冲区中提取。


库缓存 这一个步骤,决定了 SQL 语句是否需要进行硬解析。为了提升 SQL 的执行效率,我们应该尽量避免硬解析,因为在 SQL 的执行过程中,创建解析树,生成执行计划是很消耗资源的。


你可能会问,如何避免硬解析,尽量使用软解析呢?

在 Oracle 中, 绑定变量是它的一大特色。绑定变量就是在 SQL 语句中使用变量,通过不同的变量取值来改变 SQL 的执行结果。这样做的好处是能提升软解析的可能性 ,不足之处在于可能会导致生成的执行计划不够优化,因此是否需要绑定变量还需要视情况而定。


举个例子,我们可以使用下面的查询语句:

 select * from player where player_id = 10001;

你也可以使用绑定变量,如:

select * from player where player_id = :player_id;

这两个查询语句的效率在 Oracle 中是完全不同的。如果你在查询 player_id = 10001 之后,还会查询10002、10003 之类的数据,那么每一次查询都会创建一个新的查询解析。而第二种方式使用了绑定变量,那么在第一次查询之后,在共享池中就会存在这类查询的执行计划,也就是软解析。

因此,我们可以通过使用绑定变量来减少硬解析,减少 Oracle 的解析工作量。但是这种方式也有缺点,使用动态 SQL 的方式,因为参数不同,会导致 SQL 的执行效率不同,同时 SQL 优化也会比较困难。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
10月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
8月前
|
存储 移动开发 JavaScript
快应用推广连接底层技术与架构以及如何结合自身系统分销的推广逻辑和技术对接-优雅草卓伊凡|果果|Ant
快应用推广连接底层技术与架构以及如何结合自身系统分销的推广逻辑和技术对接-优雅草卓伊凡|果果|Ant
148 4
快应用推广连接底层技术与架构以及如何结合自身系统分销的推广逻辑和技术对接-优雅草卓伊凡|果果|Ant
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
1058 3
Mysql高可用架构方案
|
存储 SQL 关系型数据库
MySQL进阶突击系列(03) MySQL架构原理solo九魂17环连问 | 给大厂面试官的一封信
本文介绍了MySQL架构原理、存储引擎和索引的相关知识点,涵盖查询和更新SQL的执行过程、MySQL各组件的作用、存储引擎的类型及特性、索引的建立和使用原则,以及二叉树、平衡二叉树和B树的区别。通过这些内容,帮助读者深入了解MySQL的工作机制,提高数据库管理和优化能力。
|
9月前
|
关系型数据库 MySQL 分布式数据库
Super MySQL|揭秘PolarDB全异步执行架构,高并发场景性能利器
阿里云瑶池旗下的云原生数据库PolarDB MySQL版设计了基于协程的全异步执行架构,实现鉴权、事务提交、锁等待等核心逻辑的异步化执行,这是业界首个真正意义上实现全异步执行架构的MySQL数据库产品,显著提升了PolarDB MySQL的高并发处理能力,其中通用写入性能提升超过70%,长尾延迟降低60%以上。
|
8月前
|
人工智能 搜索推荐 数据安全/隐私保护
快应用推广联盟分销逻辑及技术架构深度解析-优雅草卓伊凡|果果|Ant
快应用推广联盟分销逻辑及技术架构深度解析-优雅草卓伊凡|果果|Ant
230 2
|
11月前
|
负载均衡 算法 关系型数据库
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL集群架构负载均衡故障排除与解决方案
本文深入探讨 MySQL 集群架构负载均衡的常见故障及排除方法。涵盖请求分配不均、节点无法响应、负载均衡器故障等现象,介绍多种负载均衡算法及故障排除步骤,包括检查负载均衡器状态、调整算法、诊断修复节点故障等。还阐述了预防措施与确保系统稳定性的方法,如定期监控维护、备份恢复策略、团队协作与知识管理等。为确保 MySQL 数据库系统高可用性提供全面指导。
|
SQL 存储 缓存
MySQL的架构与SQL语句执行过程
MySQL架构分为Server层和存储引擎层,具有高度灵活性和可扩展性。Server层包括连接器、查询缓存(MySQL 8.0已移除)、分析器、优化器和执行器,负责处理SQL语句;存储引擎层负责数据的存储和读取,常见引擎有InnoDB、MyISAM和Memory。SQL执行过程涉及连接、解析、优化、执行和结果返回等步骤,本文详细讲解了一条SQL语句的完整执行过程。
436 3
|
SQL 存储 缓存
【赵渝强老师】MySQL的体系架构
本文介绍了MySQL的体系架构,包括Server层的7个主要组件(Connectors、Connection Pool、Management Service & Utilities、SQL Interface、Parser、Optimizer、Query Caches & Buffers)及其作用,以及存储引擎层的支持情况,重点介绍了InnoDB存储引擎。文中还提供了相关图片和视频讲解。
467 2
【赵渝强老师】MySQL的体系架构
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。

热门文章

最新文章

推荐镜像

更多