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

摘要:一条 sql 查询语句是如何执行的?mysql 会先经过客户端、连接器、查询缓存、分析器、优化器、执行器等等几个步骤。
mysql> select * from T where ID=10;

上面就是一个普通的查询 sql,那么这个查询 sql 从开始执行到返回结果,中间经历了哪些过程。如果从 MySQL 的体系结构来说,这条 SQL 会经过四层(客户端、服务层、存储引擎层、物理层),然而服务层才是重要的一层,比如连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

存储引擎层是对数据的提取和存储,MySQL 存储引擎是插件式的,支持多种存储引擎(InnoDB、MyISAM、Memory 等等),每个存储引擎都有各自的优点。


连接器

要想操作 MySQL 服务,那么你先得从 MySQL 客户端到连接到 MySQL 服务器上,在经过经典的 TCP 三次握手之后,MySQL 服务器就要验证客户端输入的验证信息,比如账号、密码、IP、端口等等。

如果验证错误,那么 MySQL 会给你抛出一个错误。如果验证通过,那么 MySQL 服务器就要验证此账号的权限,之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。

连接建立完成后,如果没有后续操作,那么这个连接就是一个空闲连接,使用 show processlist; 查看该连接状态,那么他的 Command 状态就是 Sleep,表示这是系统的一个空闲连接。如果这个连接空闲时间超过 MySQL 的系统配置 wait_timeout 参数配置的话,这个连接会被 MySQL 自动关闭。如果在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒: Lost connection to MySQL server during query。这时候如果你要继续,就需要重连,然后再执行请求了。(这是 MySQL 的短连接,还有就是长连接,两种连接方式各有利弊)


查询缓存

查询缓存,前提是要开启缓存。MySQL 在执行查询之前,会先查看缓存是否命中,如果命中,会直接返回结果,一个 SQL 的查询到此就为止了。如果没有命中,那么该 SQL 会继续按照步骤往下执行。

MySQL 缓存会以 key => value 的形式存储,key = sql,value = result。但是并不建议使用缓存,因为 MySQL 的缓存命中率太低了,主要我们的 SQL 语句稍微一变,那么该缓存就失效了,既然命中率很低,那么就没有必要走 MySQL 缓存这一步了,我们要知道,多一步操作,就意味一条 SQL 会多一些耗时。所以我们一般都会使用 redis,memcache 等缓存在代替 MySQL 的缓存。

还需要注意的是,MySQL 8.0 已经把缓存整个功能给删除了。


分析器

如果没有命中缓存,那么 MySQL 就要开始真正的执行 SQL 了。在执行 SQL 之前,MySQL 会先做“词法分析”,我们输入的只是一个字符串,但是 MySQL 服务要识别出来这个字符串中,那些是 MySQL 的关键字,比如 select、from、where、limit 等等。在做完识别之后,MySQL 就要进行“语法分析”,语法分析的作用就是检查该 SQL 的语法是否符合 MySQL 语法规范。


优化器

经过分析器的检查之后,这是一条正确的可执行的查询 SQL,然后在查询之前,MySQL 会对它进行优化,因为 MySQL 表里有很多索引,有的 SQL 查询可能会比较复杂,MySQL 的优化器需要在多种执行逻辑之间(比如使用那些索引,比如联表查询单的顺序),找出优化器认为比较优化的一个方案去执行 SQL 语句。


执行器

一切准备就绪之后,就可以执行这条 SQL 查询了。在执行查询之前,MySQL 还是会检查下该账户是否有对该表操作的权限。如果没有权限,还是会返回没有权限的错误。如果有权限,那么 MySQL 会打开表,然后调用该表存储引擎的查询接口来获取数据。

执行器会把所有满足条件的行组成的记录集作为结果集返回给客户端。


参考资料:

MySQL 实战 45 讲:一条SQL查询语句是如何执行的?

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top