【Mysql专题】一条SQL在Mysql中是如何执行的

news2024/12/28 13:39:00

目录

  • 前言
  • 前置知识
  • 课程内容
    • 一、Mysql的内部组件结构
    • 1.1 Server层
    • 1.2 引擎层(Store层)
  • 二、连接器
  • 三、查询缓存(Mysql8.0后已移除)
  • 四、分析器
    • 4.1 词法分析器原理
  • 五、优化器
  • 六、执行器
  • 学习总结

前言

知其然,当知其所以然。Mysql作为我们后端的重中之重,搞懂其执行原理非常有必要。
甚至有人这么说:Java一定要搞好的三板斧有【数据结构】、【Mysql】、【Spring】。只要你能舞好这三板斧,基本上可以成为一个比较优秀的JavaCoder了。

前置知识

同学们知道,自己写出来的SQL,它的执行顺序是怎样的吗?或许有小伙伴会想:知道了又怎样,我不知道不一样写?
不一定的同学们,如果你知道了执行顺序,起码你在写SQL的时候不会四顾茫然,而是下笔如有神。下面比较重要的是,理解select语句的执行顺序。

1)查询语句顺序

  1. FROM子句:指定要查询的数据表
  2. WHERE子句:指定查询条件
  3. GROUP BY子句:按照指定的列进行分组
  4. HAVING子句:指定对分组结果的筛选条件
  5. SELECT子句:指定要查询的列
  6. ORDER BY子句:按照指定的列进行排序
  7. LIMIT子句:指定查询结果的数量

2)插入执行顺序

  1. 指定要插入的表
  2. 从INSERT语句中获取要插入的数据
  3. 检查要插入的数据是否符合表结构的约束条件
  4. 检查要插入的数据是否与表中已有的数据产生冲突
  5. 将数据插入到表中
  1. 更新执行顺序
  1. 指定要更新的表
  2. 执行WHERE子句,筛选出要更新的数据
  3. 检查要更新的数据是否符合表结构的约束条件
  4. 检查要更新的数据是否与表中已有的数据产生冲突
  5. 更新数据

4)删除执行顺序

  1. 指定要删除的表
  2. 执行WHERE子句,筛选出要删除的数据
  3. 检查要删除的数据是否符合表结构的约束条件
  4. 检查要删除的数据是否与表中已有的数据产生冲突
  5. 删除数据

课程内容

一、Mysql的内部组件结构

在介绍之前,这边还是先给大家一个比较全面的,Mysql内部组件结构图。
在这里插入图片描述
大体来说,Mysql可以分为:Server层和引擎层。

1.1 Server层

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

1.2 引擎层(Store层)

存储引擎层负责数据的存取。其架构模式是插件式的,支持Innodb、MyIsam、Memory等多个存储引擎。现在最常用的是Innodb,他从Mysql5.5.5版本开始成为了默认的存储引擎。
这是我随便截图的一个,自己创建的,创建的时候并没有去刻意指定引擎层:

CREATE TABLE `student_info` (
  `student_id` int(11) DEFAULT NULL,
  `student_name` varchar(255) DEFAULT NULL,
  `student_age` int(255) DEFAULT NULL,
  `student_score` decimal(8,1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

下面我们重点来分析连接器、查询缓存、分析器、优化器、执行器分别主要干了哪些事情。

二、连接器

不得不说,很多初学者,刚接触Mysql的时候,都有点傻傻分不清Mysql的服务端跟客户端分别是什么。简单来说,我们在服务器安装的Mysql5.X或者Mysql8.x就是服务端,如下图,用PhpStudy提示要安装的数据库服务:
在这里插入图片描述
上面这些就是服务端,它首先是一个独立的软件,跟我们Java什么的没有半毛钱关系。

既然是服务端,那我们通常就需要一些客户端去连接使用。我们常用的客户端:navicat、mysql front、jdbc、SQLyog等,其实可以看做是【可视化客户端】的一些种类,除此之外当然还有非可视化的,最典型的非可视化的就是我们在服务端上,使用mysql -h host -u root -p这种交互式的(如果你们看了我最开始的结构图,会发现,我把【Java程序】也当作是客户端的一种了)
而客户端要向mysql发起通信都必须先跟Server端建立通信连接,而建立连接的工作就是有连接器完成的。

在建立连接的时候,第一步,你会先连接到这个数据库上,这时候接待你的就是连接器。连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接命令一般是这么写的:

[root@192 ~]# mysql -h host[数据库地址] -u root[用户] -p root[密码] -P 3306

连接命令中的 mysql 是客户端工具,用来跟服务端建立连接。在完成经典的 TCP 握手后,连接器就要开始认证你的身份,这个时候用的就是你输入的用户名和密码。

  1. 如果用户名或密码不对,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
  2. 如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。

这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。用户的权限表在系统表空间的mysql的user表中。
在这里插入图片描述修改user密码:

mysql> CREATE USER 'username'@'host' IDENTIFIED BY 'password'; //创建新用户
mysql> grant all privileges on *.* to 'username'@'%'; //赋权限,%表示所有(host)
mysql> flush privileges //刷新数据库
mysql> update user set password=password(”123456″) where user=’root’;(设置用户名密码)
mysql> show grants for root@"%"; 查看当前用户的权限

连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 show processlist 命令中看到它。文本中这个图是 show processlist 的结果,其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接,关闭连接 kill <id>。
在这里插入图片描述
客户端如果长时间不发送command到Server端,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
查看wait_timeout:

mysql> show global variables like "wait_timeout";
mysql>set global wait_timeout=28800; 设置全局服务器关闭非交互连接之前等待活动的秒数

在这里插入图片描述
如果在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒: Lost connection to MySQL server during query。这时候如果你要继续,就需要重连,然后再执行请求了。
数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个(开发当中我们大多数时候用的都是长连接,把连接放在Pool内进行管理,但是长连接有些时候会导致 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了)

怎么解决这类问题呢?

  1. 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连
  2. 如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态

三、查询缓存(Mysql8.0后已移除)

常用的一些操作:

mysql>show databases; 显示所有数据库
mysql>use dbname; 打开数据库:
mysql>show tables; 显示数据库mysql中所有的表;
mysql>describe user; 显示表mysql数据库中user表的列信息);

连接建立完成后,你就可以执行 select 语句了。执行逻辑就会来到第二步:查询缓存。

查询缓存过程
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。
如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。

查询缓存缺点
但其实,大多数情况下,Mysql的查询缓存是一个鸡肋的功能。为什么呢?
因为查询缓存的失效非常频繁,Mysql的缓存失效策略是:只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。

查询缓存建议
一般建议大家在静态表里使用查询缓存,什么叫静态表呢?就是一般我们极少更新的表。比如,一个系统配置表、字典表,那这张表上的查询才适合使用查询缓存。好在 MySQL 也提供了这种【按需使用】的方式。你可以将my.cnf参数 query_cache_type 设置成 DEMAND

my.cnf
#query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE关键词时才缓存
query_cache_type=2

这样对于默认的 SQL 语句都不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 SQL_CACHE 显式指定,像下面这个语句一样:

mysql> select SQL_CACHE * from test where ID=5

查看当前mysql实例是否开启缓存机制:

mysql> show global variables like "%query_cache_type%";

监控查询缓存的命中率:

mysql> show status like'%Qcache%'; //查看运行的缓存信息

在这里插入图片描述

  • Qcache_free_blocks:表示查询缓存中目前还有多少剩余的blocks,如果该值显示较大,则说明查询缓存中的内存碎片过多了,可能在一定的时间进行整理。
  • Qcache_free_memory:查询缓存的内存大小,通过这个参数可以很清晰的知道当前系统的查询内存是否够用,是多了,还是不够用,DBA可以根据实际情况做出调整。
  • Qcache_hits:表示有多少次命中缓存。我们主要可以通过该值来验证我们的查询缓存的效果。数字越大,缓存效果越理想。
  • Qcache_inserts: 表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的情况的次数,次数越多,表示查询缓存应用到的比较少,效果也就不理想。当然系统刚启动后,查询缓存是空的,这很正常。
  • Qcache_lowmem_prunes:该参数记录有多少条查询因为内存不足而被移除出查询缓存。通过这个值,用户可以适当的调整缓存大小。
  • Qcache_not_cached: 表示因为query_cache_type的设置而没有被缓存的查询数量。
  • Qcache_queries_in_cache:当前缓存中缓存的查询数量。
  • Qcache_total_blocks:当前缓存的block数量。

PS:mysql8.0已经移除了查询缓存功能

四、分析器

如果没有命中查询缓存,就要开始真正执行语句了。这是第三步,分析sql语句。分析过程如下:

  1. 首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析
  2. 分析器先会做【词法分析】。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么
  3. MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”
  4. 做完了这些识别以后,就要做【语法分析】。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法(我们在写sql的时候经常遇到的[Err] 1064 - You have an error in your SQL syntax;就是【语法分析】器分析过后给你的结果)
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

4.1 词法分析器原理

词法分析器分成6个主要步骤完成对sql语句的分析:

  1. 词法分析
  2. 语法分析
  3. 语义分析
  4. 构造执行树
  5. 生成执行计划
  6. 执行计划

下图是SQL词法分析的过程步骤:
在这里插入图片描述
SQL语句的分析分为词法分析与语法分析,mysql的词法分析由MySQLLex(MySQL自己实现的)完成;语法分析由Bison生成。
那么除了Bison外,Java当中也有开源的词法结构分析工具例如Antlr4,ANTLR从语法生成一个解析器,可以构建和遍历解析树,可以在IDEA工具当中安装插件:antlr v4 grammar plugin。插件使用详见课程。
经过bison语法分析之后,会生成一个这样的语法树:
在这里插入图片描述
至此我们分析器的工作任务也基本圆满了。接下来进入到优化器。

五、优化器

经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。优化器有什么作用呢?
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序(不然光凭程序员自己写,很多多表联查的SQL性能都有点惨不忍睹)。比如你执行下面这样的语句,这个语句是执行两个表的 join:

mysql> select * from test1 join test2 using(ID) where test1.name=yangguo and test2.name=xiaolongnv;

上面这条sql,原则上可以这么查询:

  1. 可以先从表 test1 里面取出 name=yangguo的记录的 ID 值,再根据 ID 值关联到表 test2,再判断 test2 里面 name的值是否等于 yangguo
  2. 也可以先从表 test2 里面取出 name=xiaolongnv 的记录的 ID 值,再根据 ID 值关联到 test1,再判断 test1 里面 name 的值是否等于 yangguo

这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等等。

六、执行器

开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。

mysql> select * from test where id=1;

如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。比如我们这个例子中的表 test 中,ID 字段没有索引,那么执行器的执行流程是这样的:

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

此,这个语句就执行完成了。对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。你会在数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。

学习总结

  1. 复习sql的执行顺序,特别是查询语句的执行顺序
  2. 学习Mysql服务的内部组件结构图
  3. 学习Mysql内部各组件的作用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1048972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

排序:简单选择排序算法分析

选择排序包括简单选择排序以及堆排序。 1.算法分析 每一趟在待排序元素中选取关键字最小的元素加入有序子序列。 n个元素的简单选择排序需要n-1趟处理。 2.代码实现 //交换 void swap(int &a, int &b) {int temp a;a b;b temp; }//简单选择排序 void SelectSort…

定义豪车新理念 远航汽车亮相2023中国(天津)国际汽车展览会

近年来&#xff0c;随着汽车行业竞争持续加剧&#xff0c;老品牌面临积极转型&#xff0c;新势力则经验不足、实力欠佳&#xff0c;到底是难抵市场的风云变幻。在此背景下&#xff0c;有着“老品牌 新势力”双重基因的远航汽车可谓底气十足。作为大运集团携手博世、华为、阿里斑…

nginx 多层代理 + k8s ingress 后端服务获取客户真实ip 配置

1.nginx http 七层代理 修改命令空间&#xff1a; namespace: nginx-ingress : configmap&#xff1a;nginx-configuration kubectl get cm nginx-configuration -n ingress-nginx -o yaml添加如上配置 compute-full-forwarded-for: “true” forwarded-for-header: X-Forwa…

谱瑞PS186|替代PS186方案|TypeC转HDMI4K视频转换方案设计

谱瑞PS186/PS188/PS176,是一系列Type-C/DP转HDMI 4K60的视频转换芯片&#xff0c;其中PS186是DP 2lane转HDMI 4K60&#xff0c;若是设计Type-C转HDMI方案还需加一颗C转DP协议转换芯片&#xff0c;这样成本更高。而集睿致远CS5366单颗芯片即可实现Type-C转HDMI 4K60HZ设计方案. …

python使用mitmproxy和mitmdump抓包以及对手机

mitmproxy是一个中间人角色&#xff0c;供python抓包使用。 本机环境&#xff1a;win10 64位&#xff0c;python3.10.4。首先安装mitmproxy&#xff0c;参考我的文章 记录一下python2和python3在同一台电脑上共存使用并安装各自的库以及各自在pycharm中使用的方法-CSDN博客 一…

【轮趣-科大讯飞】M260C 环形六麦测试 2 - ROS1功能测试与唤醒、语音识别程序解析

所有内容请看&#xff1a; 博客学习目录_Howe_xixi的博客-CSDN博客https://blog.csdn.net/weixin_44362628/article/details/126020573?spm1001.2014.3001.5502原文在飞书&#xff0c;请联系我获取阅读链接&#xff0c;我太懒了

Acwing 835. Trie字符串统计

Acwing 835. Trie字符串统计 题目描述代码展示 题目描述 代码展示 //这个代码的注释好难写&#xff0c;以自己理解为主 #include<iostream>using namespace std; const int N 100010; int idx; // 各个节点的编号&#xff0c;根节点编号为0 int son[N][26];//Trie 树本…

视频增强修复工具Topaz Video AI mac中文版安装教程

Topaz Video AI mac是一款使用人工智能技术对视频进行增强和修复的软件。它可以自动降噪、去除锐化、减少压缩失真、提高清晰度等等。Topaz Video AI可以处理各种类型的视频&#xff0c;包括低分辨率视频、老旧影片、手机录制的视频等等。 使用Topaz Video AI非常简单&#xff…

油封的两种主要类型?

油封也称为轴封&#xff0c;是各类机械中不可或缺的部件。它们主要用于密封机械设备中固定部件和移动部件之间的开口。大多数应用中较常用的油封是橡胶壳油封或金属壳油封。 橡胶壳油封广泛用于存在金属壳油封因热膨胀而失效的风险的应用中。橡胶外壳油封不会生锈&#xff0c;…

Linux学习第22天:Linux中断驱动开发(一): 突如其来

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 中断作为驱动开发中很重要的一个概念&#xff0c;在实际的项目实践中经常用到。本节的主要内容包括中断简介、硬件原理分析、驱动程序开发及运行测试。其中驱动程…

【面试经典150 | 滑动窗口】最小覆盖子串

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;滑动窗口 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等…

26525-2022 精制氯化钴 学习记录

声明 本文是学习GB-T 26525-2022 精制氯化钴. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了精制氯化钴的要求、试验方法、检验规则及标志、标签、包装、运输、贮存。 本文件适用于精制氯化钴。 注&#xff1a;该产品主要用于…

ATA-P系列功率放大器——应用场景介绍

ATA-P系列功率放大器是一款理想的可放大交直流信号的功率放大器。最大输出功率可达1300Wp&#xff0c;可以驱动压电陶瓷片、叠堆型压电陶瓷、开环封装压电陶瓷以及纳米定位工作台等压电制动产品。电压增益数控可调&#xff0c;一键保存常用设置&#xff0c;提供了方便简洁的操作…

今天刷到一条有用的抖音---网站文档copy的解禁

有的时候在网上查找一些资料&#xff0c;发现些有用的东西的时候&#xff0c;兴高采烈的复制一下&#xff0c;然后网站弹出一个菜单让你付钱~~如下图&#xff1a; 此时&#xff0c;可以在该网页上&#xff0c;按F12&#xff0c;召唤出调试窗口&#xff0c;在事件监听器中&#…

亚马逊筋膜枪UL1647测试报告申请

筋膜枪&#xff0c;又称深层肌筋膜冲击仪&#xff0c;是一种通过高频冲击放松身体的软组织的软组织康复工具。[1]筋膜枪可理解为DMS&#xff08;电动深层肌肉刺激器&#xff09;的民用版本。使用时振动频率会发生变化&#xff0c;其基本功能与DMS相似。[2]筋膜枪的使用必须注意…

【AI视野·今日NLP 自然语言处理论文速览 第四十三期】Thu, 28 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 28 Sep 2023 Totally 38 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Cross-Modal Multi-Tasking for Speech-to-Text Translation via Hard Parameter Sharing Authors Brian Yan,…

安卓手机使用油猴脚本教程

下载支持油猴脚本的浏览器 请现在应用商店下载 x浏览器 &#xff0c;如果自己手机应用商店没有的话&#xff0c;可以在官网下载安装包&#xff0c;然后手动安装。 x浏览器官网 应用图标&#xff1a; 导入油猴脚本 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1…

Cannot download sources

问题 Swagger的相关包&#xff0c;没法看到注释&#xff1b;源码也下载不了&#xff0c;会报下面的错误。 解决办法是&#xff0c;通过maven&#xff0c;重新下载jar包。 报错 Cannot download sources Sources not found for: io.swagger.core.v3:swagger-annotations:2.2.…

java导出word(含图片、表格)

1.pom 引入 <!--word报告生成依赖--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupI…

kafka环境搭建以及基本原理

kafka最先是作为日志数据采集&#xff0c;后用于消息传递&#xff0c;kafka能承担tb级别数据存储&#xff0c;确保服务的可用性&#xff0c;允许少量数据的丢失 作为消息中间件就有异步、解耦、削峰三个作用 一、单机搭建 单机ip&#xff1a;192.168.64.133 下载地址&#…