一条SQL查询语句是如何执行的?

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 比较喜欢的一段话:不经一番寒彻骨,怎得梅花扑鼻香,学习是枯燥的请大家坚持! 这篇文章的是向丁奇老师学习的。不懂的自己搜一下哈!

预热


比较喜欢的一段话:不经一番寒彻骨,怎得梅花扑鼻香,学习是枯燥的请大家坚持! 这篇文章的是向丁奇老师学习的。不懂的自己搜一下哈!阅读这篇文章大概需要20分钟!


大家好,我是一位农民工(码农),也是一位打算冲击一线互联网大厂的码农。目前从事的是Java后端开发,写作分享经验是我的兴趣,我想帮助更多未来可期但是现在迷茫的人!

欢迎大家来到走向一线大厂的大门!开局前,先上几句SQL大家先热热身!


explain SELECT ID FROM t_apimonitoring

explain SELECT * FROM t_apimonitoring

explain SELECT ID FROM t_apimonitoring where ID=20

explain SELECT * FROM t_apimonitoring where ID>7000


大概就是这四句啦,都是比较基础的。分别是查询性能监控表的所有数据,查询所有ID数据,查询ID为20的数据,查询ID大于7000的所有数据。最后再一一论证是如何查询的!


工作大概半年了,我见过很多同事打开SQL面板,很大的概率是非常熟练的先输入了一遍select * from 表名然后一堆数据就出来了。以及去年大厂热点话题 <谁在写select * 给我滚蛋>。大家有没有想过为什么会这样呢?


开始


image.png

首先MySQL大体可以分为,Service层,存储引擎层两个部分。

连接器: 校验用户身份信息,校验当前用户的SQL语句权限,管理SQL连接的通道

分析器: 词法分析,语法分析。用于处理客户端的SQL语句,分析处理完之后写入缓存,如果下次命中的话直接返回提高查询效率。

优化器: 生成执行计划,索引选择(这里可以完美解释我上面抛出的SQL执行问题)

执行器: 调用操作存储引擎,捞取数据。

存储引擎: 后面会详细讲一些扩展引擎,第三方引擎,大数据量引擎等。这里会简单介绍一下Innodb与myisam


连接器

  1. 通过这个指令建立连接 mysql -h 127.0.0.1 -P 3306 -u root -p 123456
  2. 通过分配后的权限,每个用户可以操作相应的事情

image.png

  1. 建立连接之后可以通过 show processlist 查询连接状态。其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。

image.png

4.数据库连接又分为两种连接方式,一种是长连接,一种是短连接。长连接的意思就是建立连接之后,如果客户端的有请求操作则一种使用同一个连接进行交互处理。短连接的意思就是建立连接之后,并且客户端执行完自己的需求之后,就关闭了连接。

结论: 数据库建立连接这个过程是比较复杂的,所以建立尽量减少使用短连接的方式,也就是尽量使用长连接

弊端: 全部使用长连接后,你可能会发现,有些时候 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。怎么解决这个问题呢?你可以考虑以下两种方案。定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。


查询缓存

建立连接之后,就可以开始我们的操作了,比如写一些SQL语句了。MySQL拿到一个SQL请求后,会先检查缓存中是否已经执行过这条语句了,如果当前存在就直接返回这是最有的查询方式,效率也是非常高的,但是在实践中往往不建议使用缓存,因为缓存内有一个机制,当这个表发生更新的时候就会清空缓存,在真正的操作中一般都会多次更新操作的。所以就算存了缓存也用不上,除非有一些系统设置表,用户表等一些冷门的表才建议使用缓存。

使用手法:将参数query_cache_type设置成DEMAND,这样对于默认的SQL都不使用查询缓存,而真正对于一些系统设置类的静态表可以在SQL上添加以下指令实现缓存效率。

mysql> select SQL_CACHE * from T where ID=10;


分析器

分析器要做的事情主要是‘词法分析’和‘语法分析’

如果没有命中缓存就说明走到这一步了.我们看到的一串字符串,真正在执行的时候不会执行一段字符串的,所以分析器的作用就是提取字符串的指令,比如开头的SQL指令。字符串select会转换成一个查询语句,字符串t_apimonitoring会转换成表t_apimonitoring,字符串ID会转换成列ID。

转换成SQL语言之后就开始进行语法分析了,分析SQL语法是否有错误,如果没有错误的话下一步继续执行,如果有错误的话我们只需要关注use near大概就能解决一切了,所以SQL还是非常强大方便的。> 1064 - 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 'from where ss per_user' at line 1


优化器

经过分析器已经转一个字符串转换成一个SQL语句了。优化器所要做的事情就是,寻找匹配索引达到最优查询效率。 这里是t1表跟t2表进行关联,查询t1表中的c字段为10的数据并且也查询t2表中的d字段为20的共同数据。如果换一个说法这里是t2表跟t1表进行关联,查询t2表中的d字段为20的数据并且查询t1表中的c字段为10的数据的共同数据。这两个说法都是对的。但是对于SQL来说,寻找不同的索引能极大的提高性能。

mysql> select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;


执行器

分析器处理了要做什么,优化器处理了要怎么做,最后可以执行SQL语句了。在执行SQL的时候会有一步procheck验证权限的步骤,这一步我估计会有很多人会比较懵,一开始连接不也是校验权限吗。其实这两步的权限是不一样的。一开始是校验用户的大权限,执行器这里验证的是用户中对每个表的操作权限。如果有就开始调用引擎接口,如果没有就返回权限错误。

以下列SQL为例,执行SQL的步骤就是会先捞取表中的第一条数据,并且判断ID是不是为10,如果不是就跳过,继续重复操作一直找到ID为10的数据为止然后返回结果集给客户端

mysql> select * from T where ID=10;

你会在数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。我们后面会专门有一篇文章来讲存储引擎的内部机制,里面会有详细的说明。


结尾


感谢各位小伙伴看完这篇文章,这篇文章大概介绍了一下SQL的运行过程。是不是又自信了一点呢?


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8月前
|
SQL
sql语言之子查询语句
sql语言之子查询语句
|
SQL Java 数据库连接
springboot-maven项目+jpa 运行过程中执行resources下sql脚本文件-ClassPathResource和ScriptUtils.executeSqlScript的使用
springboot-maven项目+jpa 运行过程中执行resources下sql脚本文件-ClassPathResource和ScriptUtils.executeSqlScript的使用
501 0
springboot-maven项目+jpa 运行过程中执行resources下sql脚本文件-ClassPathResource和ScriptUtils.executeSqlScript的使用
|
6天前
|
SQL 数据库
SQL数据库基础语法-查询语句
SQL数据库基础语法-查询语句
|
19天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
|
5月前
|
SQL 关系型数据库 MySQL
【MySQL数据库】SQL查询语句总结
【MySQL数据库】SQL查询语句总结
69 0
|
1月前
|
SQL 存储 缓存
【MySQL实战笔记】01.一条SQL查询语句是如何执行的?
【4月更文挑战第3天】MySQL执行SQL的流程包括连接器、查询缓存、分析器、优化器和执行器。连接器负责建立连接、权限验证,查询缓存(MySQL 8.0已移除)存储查询结果,分析器解析SQL确保语法正确,优化器选择最佳索引和查询路径,执行器执行查询并管理权限。连接器使用长连接可能导致内存问题,可定期断开或使用`mysql_reset_connection`。注意,更新操作会导致查询缓存失效。
21 3
|
2月前
|
SQL 存储 关系型数据库
sql数据库查询语句大全
sql数据库查询语句大全
|
2月前
|
SQL Oracle 关系型数据库
通用SQL数据库查询语句精华使用简介
通用SQL数据库查询语句精华使用简介
|
2月前
|
SQL 数据库 内存技术
学习数据库要掌握的54条SQL查询语句
学习数据库要掌握的54条SQL查询语句
16 0
|
2月前
|
SQL 存储 关系型数据库
MySQL 常用30种SQL查询语句优化方法
MySQL 常用30种SQL查询语句优化方法
79 0