MySQL的执行顺序
学习java后端离不开MySQL,但是对于一条SQL语句,是如何执行,以及最终返回结果的生成一直有点黑盒,本次梳理了MySQL的执行过程,顺便弄清了一直没懂的Innodb中索引下推优化的过程。
一条SQL语句的执行大概分为六个部分 初始语句-->语法和词法解析 -->语义解析-->进行查询优化,生成执行计划 -->调用执行引擎执行执行计划得到结果 --> 执行引擎返回结果
1:建立连接:
客户端想要查询数据库,首先要建立连接池,进行权限的校验
2:查询缓存
mysql维护一个缓冲池,使用语句为key,查询的结果为value ,但由于实际中语句完全重复的情况很少出现,在查询前还需要进行查询一遍缓存,而命中率很低,因此在在MYsql 3.8之后就废除了
3:解析器进行词法语法分析
首先进行词法分析,生成词法树,这一步不会对表名和列表名进行检查,只会检查是否符合基本语法,然后进行语法分析,这一步对表名和列名进行校验,如果不存在就会报错
4:预处理器
如果每次都是一条新的sql语句从编译到运行结束,则被称为 Immediate Statements (即时 SQL),这种SQL每次执行都需要进行词法语法分析,比较耗时。但在实际的生产中,经常会复用一句SQL,改变的只是参数条件,因此采取预编译的SQL
MyBatis提供的占位符也就是预编译的SQL, 这样可以防止SQL 注入,也提升了执行效率,避免了每次执行都需要进行词法语法分析。
5:查询优化器
预处理器已经对sql的执行进行了一次优化,但这个只是公共的优化而已,在查询优化器,会按照一定原则来得到她认为的目标SQL在当前情形下最有效的执行路径,优化器的目的是为了得到目标SQL的执行计划,查询优化器有两种方式
RBO— 基于规则的优化器:
RBO所用的判断规则是一组内置的规则,这些规则是硬编码在数据库的编码中的,RBO会根据这些规则去从SQL诸多的路径中来选择一条作为执行计划(比如在RBO里面,有这么一条规则:有索引使用索引。那么所有带有索引的表在任何情况下都会走索引)所以,RBO现在被很多数据库抛弃(oracle默认是CBO,但是仍然保留RBO代码,MySQL只有CBO)
RBO最大问题在于硬编码在数据库里面的一系列固定规则,来决定执行计划。并没有考虑目标SQL中所涉及的对象的实际数量,实际数据的分布情况,这样一旦规则不适用于该SQL,那么很可能选出来的执行计划就不是最优执行计划了。
CBO—Cost_Based Potimizer 基于成本的优化器:
CBO在会从目标诸多的执行路径中选择一个成本最小的执行路径来作为执行计划。这里的成本他实际代表了MySQL根据相关统计信息计算出来目标SQL对应的步骤的IO,CPU等消耗。也就是意味着数据库里的成本实际上就是对于执行目标SQL所需要IO,CPU等资源的一个估计值。而成本值是根据索引,表,行的统计信息计算出来的。
6:执行计划
查询语句后,经过sql的优化器,会产生一个执行计划。根据MySQL执行计划的输出,分析索引使用情况、扫描的行数可以预估查询效率;进而可以重构SQL语句、调整索引,提升查询效率。
7:执行引擎
根据执行计划调用执行引擎获得需要的数据,并返回给客户端
索引下推优化
索引下推的优化针对的是Innode引擎,在模糊匹配时,由于最左匹配,会导致索引失效,从而导致大量的回表操作,在没有索引下推时,会先调用执行引擎获取首先匹配的数据,然后再回表查询已匹配数据是否符合条件,类似于子查询,而采取了索引下推优化后,在第一次查询时就会判断是否符合条件,减少了回表次数,因此改善了性能