一条 SQL 语句执行过程


Posted in MySQL onMarch 17, 2022

一、MySQL 体系架构

一条 SQL 语句执行过程

- 连接池组件

  • 1、负责与客户端的通信,是半双工模式,这就意味着某一固定时刻只能由客户端向服务器请求或者服务器向客户端发送数据,而不能同时进行。
  • 2、验证用户名和密码是否正确(数据库 MySQL 的 user 表中进行验证),如果错误返回错误通知Access denied for user 'root'@'localhost'(using password:YES);如果正确,则会去 MySQL 的权限表查询当前用户的权限。

- 缓存组件

也称为查询缓存,存储的数据是以键值对的形式进行存储,如果开启了缓存,那么在一条查询 SQL 语句进来时会先判断缓存中是否包含当前的 SQL 语句键值对,如果存在直接将其对应的结果返回,如果不存在再执行后面一系列操作。如果没有开启则直接跳过。

show  variables  like  'have_query_cache'; # 查看缓存配置:
show  variables  like  'query_cache_type'; # 查看是否开启
show  variables  like  'query_cache_size'; # 查看缓存占用大小
show  status  like  'Qcache%'; # 查看缓存状态信息

一条 SQL 语句执行过程

一条 SQL 语句执行过程

缓存失效场景:

  • 查询语句不一致。前后两条查询 SQL 必须完全一致;
  • 查询语句中含有一些不确定的值时,则不会缓存。比如 now()、current_date()、curdate()、curtime()、rand()、uuid() 等;
  • 不使用任何表查询。如 select 'A';
  • 查询 mysql、information_schema 或 performance_schema 数据库中的表时,不会走查询缓存;
  • 在存储的函数,触发器或事件的主体内执行的查询;
  • 如果表更改,则使用该表的所有高速缓存查询都变为无效并从缓存中删除,这包括使用 MERGE 映射到已更改表的表的查询。一个表可以被许多类型的语句改变,如 insert、update、delete、truncate table、alter table、drop table、drop database。

通过上面的失效场景可以看出缓存是很容易失效的,所以如果不是查询次数远大于修改次数的话,使用缓存不仅不能提升查询效率还会拉低效率(每次读取后需要向缓存中保存一份,而缓存又容易被清除)。所以在 MySQL5.6 默认是关闭缓存的,并且在 8.0 直接被移除了。当然,如果场景需要用到,还是可以使用的。

开启:

在配置文件(linux 下是安装目录的 cnf 文件,windows 是安装目录下的 ini 文件)中,增加配置: query_cache_type = 1

一条 SQL 语句执行过程

# 指定 SQL_NO_CACHE,SQL_CACHE 同理。
SELECT  SQL_NO_CACHE  *  FROM  student  WHERE age > 20; 

- 分析器

对客户端传来的 SQL 进行分析,这将包括预处理与解析过程,并进行关键词的提取、解析,并组成一个解析树。具体的解析词包括但不局限于 select/update/delete/or/in/where/group by/having/count/limit 等,如果分析到语法错误,会直接抛给

客户端异常:ERROR:You have an error in your SQL syntax.。

select *  from user where userId = 1234;

在分析器中就通过语义规则器将 select from where 这些关键词提取和匹配出来,MySQL 会自动判断关键词和非关键词,将用户的匹配字段和自定义语句识别出来。这个阶段也会做一些校验:比如校验当前数据库是否存在 user 表,同时假如 user 表中不存在 userId 这个字段同样会报错:unknown column in field list.

- 优化器

进入优化器说明 SQL 语句是符合标准语义规则并且可以执行。优化器会根据执行计划选择最优的选择,匹配合适的索引,选择最佳的方案。比如一个典型的例子是这样的:

表 T,对 A、B、C 列建立联合索引 —— (A,B,C),在进行查询的时候,当 SQL 查询条件是:select xx where B=x and A=x and C=x。很多人会以为是用不到索引的,但其实会用到,虽然索引必须符合最左原则才能使用,但是本质上,优化器会自动将这条 SQL 优化为:where A=x and B=x and C=x,这种优化会为了底层能够匹配到索引,同时在这个阶段是自动按照执行计划进行预处理,MySQL 会计算各个执行方法的最佳时间,最终确定一条执行的 SQL 交给最后的执行器。

优化器会根据扫描行数、是否使用临时表、是否排序等来判断是否使用某个索引,其中扫描行数的计算可以通过统计信息来估算得出,而统计信息可以看作是索引唯一数的数量,可以使用部分采样来估算,具体就是选择 N 个数据页,统计这些页上数据的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了。但是因为索引数据会变化,所以索引的统计信息也会变化。当变更的数据行数超过 1/M 的时候,就会重新计算一次统计信息。

关于统计信息可以选择是否持久化::通过 innodb_stats_persistent,设置为 on 的时候,表示统计信息会持久化存储。这时,默认的 N 是 20,M 是 10。设置为 off 的时候,表示统计信息只存储在内存中。这时,默认的 N 是 8,M 是 16。

没有使用最优索引如何优化:

  • 1、虽然会自动更新统计信息,但是但是不能保证统计信息是最新值,这就可能导致优化器选择了不同的索引导致执行变慢,所以可以通过 analyze table 表名 来重新计算索引的统计信息;
  • 2、在表名后面添加 force index(索引名) 语句来强制使用索引(不建议);
  • 3、将 SQL 进行修改成优化器可以选最优索引的实现方式;
  • 4、新建一个最优索引或者删除优化器误用的索引;

- 执行器

执行器会调用对应的存储引擎执行 SQL,主流的是 MyISAM 和 Innodb。

一条 SQL 语句执行过程

二、写操作执行过程

一条 SQL 语句执行过程

三、读操作执行过程

在 MySQL 5.6 之后引入了 索引下推(Index Condition Pushdown),所以在查询操作上会有一个 Index Filter 和 Table Filter 的过程,查询的流程图大致可以用下面这张图来概括:

一条 SQL 语句执行过程

四、SQL执行顺序

一条 SQL 语句执行过程

到此这篇关于一条 SQL 语句执行过程的文章就介绍到这了,更多相关SQL 执行过程内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
my.ini优化mysql数据库性能的十个参数(推荐)
May 26 MySQL
MYSQL数据库使用UTF-8中文编码乱码的解决办法
May 26 MySQL
MySQL 四种连接和多表查询详解
Jul 16 MySQL
MySQL令人大跌眼镜的隐式转换
Aug 23 MySQL
MySQL命令无法输入中文问题的解决方式
Aug 30 MySQL
MySQL中varchar和char类型的区别
Nov 17 MySQL
mysql timestamp比较查询遇到的坑及解决
Nov 27 MySQL
Mysql事务索引知识汇总
Mar 17 MySQL
提高系统的吞吐量解决数据库重复写入问题
Apr 23 MySQL
详细介绍MySQL中limit和offset的用法
May 06 MySQL
MySql如何将查询的出来的字段进行转换
Jun 14 MySQL
MySQL慢查询中的commit慢和binlog中慢事务的区别
Jun 16 MySQL
Mysql事务索引知识汇总
Mar 17 #MySQL
MySQL慢查询优化解决问题
Mar 17 #MySQL
MySQL日期时间函数知识汇总
MySQL优化常用的19种有效方法(推荐!)
MySQL多表查询机制
MySQL高级进阶sql语句总结大全
Mar 16 #MySQL
一条慢SQL语句引发的改造之路
You might like
PHP 查找字符串常用函数介绍
2012/06/07 PHP
php中并发读写文件冲突的解决方案
2013/10/25 PHP
PHP实现简单实用的验证码类
2015/07/29 PHP
yii的入口文件index.php中为什么会有这两句
2016/08/04 PHP
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
ExtJs默认的字体大小改变的几种方法(自己整理)
2013/04/18 Javascript
JQuery实现点击div以外的位置隐藏该div窗口
2013/09/13 Javascript
js实现按一下删除键删除整个单词附demo
2014/09/05 Javascript
JS对象与json字符串格式转换实例
2014/10/28 Javascript
jQuery实现复选框批量选择与反选的方法
2015/06/17 Javascript
bootstrap laydate日期组件使用详解
2017/01/04 Javascript
javascript中神奇的 Date对象小结
2017/10/12 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
JavaScript 点击触发复制功能实例详解
2018/11/02 Javascript
layer弹出层自定义提交取消按钮的例子
2019/09/10 Javascript
基于form-data请求格式详解
2019/10/29 Javascript
VUE中鼠标滚轮使div左右滚动的方法详解
2020/12/14 Vue.js
学习python的几条建议分享
2013/02/10 Python
Python抓取京东图书评论数据
2014/08/31 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
多个应用共存的Django配置方法
2018/05/30 Python
基于Numpy.convolve使用Python实现滑动平均滤波的思路详解
2019/05/16 Python
Python TCP通信客户端服务端代码实例
2019/11/21 Python
python 协程 gevent原理与用法分析
2019/11/22 Python
python实现输入的数据在地图上生成热力图效果
2019/12/06 Python
Tensorflow tf.nn.depthwise_conv2d如何实现深度卷积的
2020/04/20 Python
Python常用base64 md5 aes des crc32加密解密方法汇总
2020/11/06 Python
收藏!10个免费高清视频素材网站!【设计、视频剪辑必备】
2021/03/18 杂记
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
皮尔·卡丹巴西官方商店:Pierre Cardin
2017/07/21 全球购物
周年庆典邀请函范文
2014/01/23 职场文书
采购部经理岗位职责
2014/02/10 职场文书
师德演讲稿范文
2014/05/06 职场文书
2014年作风建设心得体会
2014/10/22 职场文书
纯html+css实现Element loading效果
2021/08/02 HTML / CSS
万能密码的SQL注入漏洞其PHP环境搭建及防御手段
2021/09/04 SQL Server