为了了解这个问题,先从Mysql的架构说起,对于Mysql来说,大抵能够分为3层架构。

第一层作为客户端和服务端的连贯,连接器负责解决和客户端的连贯,还有一些权限认证之类。比方客户端通用用户名明码连贯到Mysql服务器,还有对于数据库表的执行权限。

第二层是核心层,基本上Mysql大部分的外围性能都在这一层,包含查问缓存、解析器、优化器之类,比方SQL解析、优化、索引抉择,到最初生成执行打算。

第三层则是存储引擎了,Mysql通过执行引擎间接调用存储引擎API查询数据库中数据。

通过Mysql的架构分层,咱们首先就能够很清晰的理解到一个SQL的大略的执行过程。

  1. 首先客户端发送申请到服务端,建设连贯。
  2. 服务端先看下查问缓存是否命中,命中就间接返回,否则持续往下执行。
  3. 接着来到解析器,进行语法分析,一些零碎关键字校验,校验语法是否合规。
  4. 而后优化器进行SQL优化,比方怎么抉择索引之类,而后生成执行打算。
  5. 最初执行引擎调用存储引擎API查问数据,返回后果。

这就是一个很概括性的SQL执行过程,接下来,具体到每个步骤具体阐明一下。

查问缓存

如果你翻看Mysql的官网文档就会晓得,查问缓存在5.7.20版本曾经被弃用,并且8.0的版本曾经删除了。为啥要删除,可能感觉太鸡肋了吧。

咱们能够通过命令来查看查问缓存是否可用。

mysql> SHOW VARIABLES LIKE 'have_query_cache';+------------------+-------+| Variable_name    | Value |+------------------+-------+| have_query_cache | YES   |+------------------+-------+

除此之外,查问缓存还有一些外围参数。更具体的阐明能够参考官网文档。

query_cache_type:是否关上查问缓存,值为0\1\2,别离对应为OFF\ON\DEMAND,ON的话则代表开启查问缓存,然而能够通过SELECT SQL_NO_CACHE来手动禁用,DEMAND则代表只缓存以SELECT SQL_CACHE结尾的SQL语句。

query_cache_limit:缓存后果大小限度,如果查问后果超过大小则不会被缓存,默认是1M大小。

query_cache_size:为查问缓存调配的内存大小,他是1024的整数倍。

query_cache_min_res_unit:查问缓存分配内存块的最小单位,默认为4KB。这是查问缓存分配内存的根本单位,即使比方查问的数据只有1个字节,也会依照最小内存单元大小来分配内存空间。

在进行SQL解析之前,零碎会判断查问缓存是否关上,如果关上,就拿缓存中的查问和传入的查问比拟,如果齐全一样,就会从缓存中间接返回。

然而须要特地留神的是,无论大小写、空格还是正文,都会影响缓存的命中后果,也就是说必须齐全一样!

比方以下的SQL大小写不同、多了空格都无奈命中查问缓存。

select * from user;SELECT * from user;select   * from user;

解析器&预处理器

如果查问缓存未命中,就会进入失常的SQL执行环节。

首先就像咱们失常的业务开发一样,第一步都是对参数的规定校验,Mysql也一样,解析器会进行词法语法分析,基于语法规定对SQL进行校验。

比方关键字是否应用正确啊,或者说关键字程序是不是正确,比如说你把select写成了selctorder by写成了by order

如果校验OK,那么就生成一颗“解析树”。

接着预处理器就是进一步根据非法规定生成的解析树进行校验,比方表名、列名是否存在等等。

优化器

如果说解析器和预处理器是咱们业务逻辑的前置校验环节,优化器就是真正的解决业务逻辑的中央。

一条查问SQL能够有N种执行形式,优化器的最终目标是找到最好的执行打算,交给执行引擎去执行。

然而理论应用中咱们常常会发现,Mysql常常有抉择错索引的状况,我明明有更快的索引,后果它不必,导致搞出了慢查问。

这是因为Mysql的优化器是基于老本模型的优化器,他只是基于已有的老本计算公式来抉择一个老本最低的执行形式,这个执行形式不肯定会是最快的,只能说大多数时候,优化器的抉择比咱们本人的抉择更精确。

总的来说,这个优化过程太简单了,流程大抵就是下图所示,更具体的内容能够看《数据库查问优化器的艺术原理解析与SQL性能》这本书(我切实是懒得看了,吐了)。

执行引擎

大部分外围的事件曾经被优化器解决完了,最初执行引擎只有依据生成好的执行打算查问数据返回就好了,这一步绝对就挺简略了。

执行引擎只须要依据执行打算的指令调用存储引擎的API就能够了。

当然这一步如果能够缓存查问后果,那么就在这个阶段把查问后果缓存下来,而后把后果返回给客户端就能够了。

总结

一图胜千言。