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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 比较喜欢的一段话:不经一番寒彻骨,怎得梅花扑鼻香,学习是枯燥的请大家坚持! 这篇文章的是向丁奇老师学习的。不懂的自己搜一下哈!

预热


比较喜欢的一段话:不经一番寒彻骨,怎得梅花扑鼻香,学习是枯燥的请大家坚持! 这篇文章的是向丁奇老师学习的。不懂的自己搜一下哈!阅读这篇文章大概需要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的运行过程。是不是又自信了一点呢?


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
1月前
|
SQL 监控 关系型数据库
一键开启百倍加速!RDS DuckDB 黑科技让SQL查询速度最高提升200倍
RDS MySQL DuckDB分析实例结合事务处理与实时分析能力,显著提升SQL查询性能,最高可达200倍,兼容MySQL语法,无需额外学习成本。
|
1月前
|
SQL 存储 关系型数据库
MySQL体系结构详解:一条SQL查询的旅程
本文深入解析MySQL内部架构,从SQL查询的执行流程到性能优化技巧,涵盖连接建立、查询处理、执行阶段及存储引擎工作机制,帮助开发者理解MySQL运行原理并提升数据库性能。
|
29天前
|
SQL 监控 关系型数据库
SQL优化技巧:让MySQL查询快人一步
本文深入解析了MySQL查询优化的核心技巧,涵盖索引设计、查询重写、分页优化、批量操作、数据类型优化及性能监控等方面,帮助开发者显著提升数据库性能,解决慢查询问题,适用于高并发与大数据场景。
|
5月前
|
SQL 数据挖掘 数据库
第三篇:高级 SQL 查询与多表操作
本文深入讲解高级SQL查询技巧,涵盖多表JOIN操作、聚合函数、分组查询、子查询及视图索引等内容。适合已掌握基础SQL的学习者,通过实例解析INNER/LEFT/RIGHT/FULL JOIN用法,以及COUNT/SUM/AVG等聚合函数的应用。同时探讨复杂WHERE条件、子查询嵌套,并介绍视图简化查询与索引优化性能的方法。最后提供实践建议与学习资源,助你提升SQL技能以应对实际数据处理需求。
314 1
|
2月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
158 18
|
7月前
|
SQL 运维 监控
SQL查询太慢?实战讲解YashanDB SQL调优思路
本文是Meetup第十期“调优实战专场”的第二篇技术文章,上一篇《高效查询秘诀,解码YashanDB优化器分组查询优化手段》中,我们揭秘了YashanDB分组查询优化秘诀,本文将通过一个案例,助你快速上手YashanDB慢日志功能,精准定位“慢SQL”后进行优化。
|
2月前
|
SQL 人工智能 数据库
【三桥君】如何正确使用SQL查询语句:避免常见错误?
三桥君解析了SQL查询中的常见错误和正确用法。AI产品专家三桥君通过三个典型案例:1)属性重复比较错误,应使用IN而非AND;2)WHERE子句中非法使用聚合函数的错误,应改用HAVING;3)正确的分组查询示例。三桥君还介绍了学生、课程和选课三个关系模式,并分析了SQL查询中的属性比较、聚合函数使用和分组查询等关键概念。最后通过实战练习帮助读者巩固知识,强调掌握这些技巧对提升数据库查询效率的重要性。
95 0
|
7月前
|
SQL 索引
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
|
3月前
|
SQL
SQL中如何删除指定查询出来的数据
SQL中如何删除指定查询出来的数据
|
5月前
|
SQL 关系型数据库 MySQL
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路