在我写好一条sql,发送给MySQL服务器,mysql经历了那些处理,最后返回给我们结果。
先看一下他的执行流程:(我从网上找的一个《高性能mysql》中的插图)
如上图他的执行流程:
1、查询缓存。如果缓存命中就直接返回,后面的步骤不执行。
2、解析器。把sql解析成解析树。
3、预处理。处理解析树,进行一些基本判断。
4、查询优化器。吧解析树交给优化器,优化器会经过以系列的优化,优化器可能不是非常精确,但绝对比你的小聪明要精确。
5、 查询执行引擎。他就一步一步的去执行查询执行计划里的命令
6、返回结果,进行缓存。返回给客户端。
我们来详细的来了解一下,各个环节的执行。
(1) mysql客户端与服务间的通信
答:用书上的话说,他们的通信是“半双工”的。意思就是,只有一个人能发送请求,一旦发送就不会停止只到传输结束。比如说:我们从mysql请求一个数据没有LIMIT限制条数,我在得到第十条的时候主动结束请求。你以为结束了,其实mysql服务器已经全部传送给你了,你只不过是从内存中一条条取罢了。
(2) 查询缓存
答:查询缓存是非常快的。但是查询缓存也是有条件的,首先缓存得是开启状态,查询的sql会和缓存中的sql进行对比,他们通过哈希来检查的。如果有这条缓存那就会,判断连接的用户是否有访问权限。
(3) 解析器
答:就是把sql语句通过使用mysql的语法规则和解析查询,来判断这条sql是否存在语法错误和单双引是否匹配,得到一个解析树。(判断sql是否可执行)
(4) 预处理器
答:就是我先去看看这个解析树里的 表名、字段名是否存在。看看名字是否有歧义,如和mysql关键字冲突等。
(5)、查询优化器
答:简单来说,选择一个最优的执行计划。优化器就对这个sql进行分析,重构,选择索引,数据的统计,然后进行各种优化得到多个执行计划。再从这些执行计划中选择一个“他认为最优”的进行执行。
优化器得到的执行计划并不一定是最优的有很多的外在条件会给他制造错觉。
如:统计信息不准确。mysql依赖储存引擎提供的统计信息来评估成本。但是有的储存引擎储存提供的信息就可能不准确的。好比InnoDb,不可能维护一个精确的统计信息。
执行计划的成本估算不等于实际要执行的成本。好比,有些数据页是有序的,有些在内存中。mysql层面并不清楚。所以有时执行更多的数据页,反而需要更少的I/O操作。
mysql不会去考虑其他的并发执行的查询。
查询优化器,给你的执行任务不一定是最优的,但是建议你不要去人为的通过一些命令去干扰它的优化。
数据和索引的统计信息:
这些信息mysql服务器是没有的,他们在储存引擎中,所以就需要调用储存引擎的API来获取这些信息。每个表有或索引有多少个页面,他们的基数是多少,有多少行,索引的长度等一系列的信息都需要去储存引擎中获取。
(6) 查询执行引擎
答:就是根据执行计划一步一步的去执行命令,在这过程大量的操作是需要调用储存引擎API接口来完成。完成所有的数据查询。
(7)返回数据给客户端
答:这时候会吧结果放到查询缓存中,这个返回是查询出来一个条就返回一个条,不是等全部查完在一起返回的。哪有那么多内存给你用,客户端哪能等你这么长时间。