以一条简单的SQL为例。
mysql> select * from T where ID=10;
我们看到的只是一条输入语句,但是在MYQL里面有他的一套执行流程,今天来分析一下这个问题。
基本架构图
首先,给出MYSQL的基本架构图。MYSQL可以分成Server层和存储引擎层。Server层包含连接器,分析器,优化器,执行器等,这和数据库使用的是哪种存储引擎没关系,是跨存储引擎的,核心功能都包含在这一层了。
引擎层主要是数据的存储和提取,如果不去指定默认的是INNODB。
一,连接器
开始会建立和数据库的连接,
mysql -h$ip -P$port -u$user -p
他会带着你提供的用户名和密码到表里找,如果用户名或者密码不对,会报一个“Access denied for user”的错误。接着会去查当前用户的权限,后续的权限检验也是会基于这个查询结果的。
如果此时已经成功创建了连接,这个时候用管理员账号来修改当前用户的权限,是没用的,必须要重新登录才能生效。
二,分析器
就是提取出关键字,相当于语法分析。比如上面这条SQL,会将select,from,where这些关键字提取出来,from后面应该是一张表,那么如果发现T不是数据库里的表,这个时候会报错。
三,优化器
如果一张表里面有多个索引或者需要几张表联查,那么需要确定一个比较好的方案(执行顺序),比如使用哪个索引啊,先查哪个表啊。
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
以上面这条SQL为例,一种方案是先到t1里面查c=10的,然后再去t2里面查,另一种方案是先到t2里面查d=20的再到t1里面查c=10的。看起来逻辑上没啥差别但是实际上他会估算出一个它认为更好的方案(他有他的计算逻辑,但是不一定真的就是最好的)。
四,执行器
就是去调用存储引擎的接口,如果是INNODB就去调INNODB的,是MYISAM就去调MYISM的查询接口(屏蔽了不同引擎带来的差异)。以我们的查询语句为例,因为没索引,就从第一条记录开始遍历,如果发现c=10,就把他存在结果集里面,如果不是10,就接着往下依次判断,直到最后一条记录,最后把结果集返回给客户端。
注意: 在执行器执行之前,需要去判断有没有查询的权限,有权限才能往后执行。
对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。
你会在数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。