一条 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 相关文章推荐
MySQL GRANT用户授权的实现
Jun 18 MySQL
MySQL的安装与配置详细教程
Jun 26 MySQL
一篇文章带你深入了解Mysql触发器
Aug 02 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
MySQL中varchar和char类型的区别
Nov 17 MySQL
防止web项目中的SQL注入
Dec 06 MySQL
关于k8s环境部署mysql主从的问题
Mar 13 MySQL
mysql insert 存在即不插入语法说明
Mar 25 MySQL
mysql 体系结构和存储引擎介绍
May 06 MySQL
Mysql中@和@@符号的详细使用指南
Jun 05 MySQL
mysql实现将字符串字段转为数字排序或比大小
Jun 14 MySQL
MySQL导致索引失效的几种情况
Jun 25 MySQL
Mysql事务索引知识汇总
Mar 17 #MySQL
MySQL慢查询优化解决问题
Mar 17 #MySQL
MySQL日期时间函数知识汇总
MySQL优化常用的19种有效方法(推荐!)
MySQL多表查询机制
MySQL高级进阶sql语句总结大全
Mar 16 #MySQL
一条慢SQL语句引发的改造之路
You might like
mysql 性能的检查和优化方法
2009/06/21 PHP
php文件缓存方法总结
2016/03/16 PHP
php使用curl通过代理获取数据的实现方法
2016/05/16 PHP
Docker配置PHP开发环境教程
2016/12/21 PHP
Jquery 获取checkbox的checked问题
2011/11/16 Javascript
设为首页加入收藏兼容360/火狐/谷歌/IE等主流浏览器的代码
2013/03/26 Javascript
对于Form表单reset方法的新认识
2014/03/05 Javascript
微信分享的标题、缩略图、连接及描述设置方法
2014/10/14 Javascript
基于jQuery实现最基本的淡入淡出效果实例
2015/02/02 Javascript
javascript实现验证IP地址等相关信息代码
2015/05/10 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
2016/04/15 Javascript
又一款js时钟!transform实现时钟效果
2016/08/15 Javascript
JS简单实现表格排序功能示例
2016/12/20 Javascript
微信小程序中页面FOR循环和嵌套循环
2017/06/21 Javascript
Vue.js实现实例搜索应用功能详细代码
2017/08/24 Javascript
解决在vue项目中,发版之后,背景图片报错,路径不对的问题
2018/03/06 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
es6 filter() 数组过滤方法总结
2019/04/03 Javascript
详解keep-alive + vuex 让缓存的页面灵活起来
2019/04/19 Javascript
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
2019/08/20 Javascript
Node如何后台数据库使用增删改查功能
2019/11/21 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
Element Backtop回到顶部的具体使用
2020/07/27 Javascript
Vue中inheritAttrs的使用实例详解
2020/12/31 Vue.js
[01:03:33]Alliance vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
浅谈Python基础—判断和循环
2019/03/22 Python
Python列表对象实现原理详解
2019/07/01 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
python语言中有算法吗
2020/06/16 Python
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
MyHeritage美国:家族史研究和DNA测试的领先服务
2019/05/27 全球购物
结婚典礼证婚词
2014/01/11 职场文书
网络工程专业自荐信范文
2014/03/16 职场文书
离婚协议书范文2014(夫妻感情破裂)
2014/12/14 职场文书
迁徙的鸟观后感
2015/06/09 职场文书
幼儿园开学家长寄语(2016春季)
2015/12/03 职场文书