这是我参与8月更文挑战的第2天。
宏观
我们先从宏观上了解mysql的架构:
执行流程大致如下:
1、客户端发送一条查询SQL给服务器
2、服务器先检查查询缓存,如果命中了缓存,则立即返回缓存中的结果,否则进入下一阶段。
3、服务端对SQL进行解析、预处理,再由优化器生成对应的执行计划。
4、mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。
5、将查询的结果返回给客户端。
下面简单说明每一阶段的功能:
一、连接器
这一个组件完成的功能是客户端与服务器之间的连接,也就是第一步。在我们输入mysql的用户密码之后(比如:mysql -uroot -p123456),连接器就会验证我们的账号密码是否正确,如果正确,就会连接成功,但是只会拥有当前账号的权限,如果不正确,就会提示连接失败。 当建立好连接之后,客户端和mysql只能进行同步操作,也就是说当msyql给客户端发请求后,必须等到mysql的响应才能进行下一步操作。
二、查询缓存
缓存中存放的是一个map,key值是查询的SQL语句,value是通过SQL查询出来的值,如果客户端发来一个查询SQL,发现可以从该map中取到对应的值,则直接返回,不需要进行后面的一系列操作。但是一般不建议使用缓存,因为我们对数据库的更改是非常频繁的,所以,即使是同一条SQL,查询出来的值也会经常不同,这就意味着缓存会失效,所以从mysql8开始,缓存这个功能已经去除了。
三、解析器、预处理器
这两个是用来解析我们的SQL语句;解析器先会做词法分析,比如看关键字(select,from)是否拼写正确,关键字的顺序是否正确,如果都没有问题,则会交给预处理器,会进一步查看我们写的表名、字段名是否正确,如果没有问题,则会将我们写的字符串解析成真正的内容。然后进一步进行语法分析,分析我们这条SQL是否存在语法问题,如果有问题就会产生“You have an error in your SQL syntax”这条错误。
四、查询优化器
查询优化器会优化我们的SQL语句,来提高SQL的性能。一条SQL语句有很多种执行的方式,优化器会找到性能最好的方式进行执行。比如我们都知道在使用复合索引的时候一定要遵循最左前缀法则,但是如果不遵循该法则,优化器也会进行优化并选择最佳方式。
需要注意的是,优化器并不是总是会优化成功我们的SQL,所以我们在写SQL时,还是要尽量把性能提升。
五、查询执行引擎
当mysql执行完上面几个阶段之后,就要进行查询操作;在执行查询操作之前,它会先判断用户的权限,如果该用户具有查询的权限,就会根据存储引擎来调用该引擎的api,进行查询操作。
微观
当我们写一条SQL时,书写的顺序如下:
select distinct..from..on..where..group by..having..order by..limit
但是mysql的实际执行顺序如下:
from, on, where, group by, having, select distinct, order by,limit
根据以上的执行顺序,我们可以可以判断出在哪个关键字后面应该进行哪些操作,比如:select 是在group by 执行之后,所以当我们使用分组函数时(count、max、min、avg),一定要将分组函数放在select的后面,不能放在where后面,因为只有group by 分完组之后,才能使用分组函数。