概述
今天开始简单了解mysql的一些底层技术,而不再只知增删改查。
select * from tab
复制代码
可能这是史上最简单的一条SQL了吧,其所表达的意思我也就不多说了,那么这么简单的一条语句从客户端发送到MySQL服务器,以及从服务器返回查询的结果究竟是经历怎么样一个过程呢?
胖子不是一口吃成的,所以下面我也只是简单描述这其中的步骤,并不会追求描述每一个步骤的具体实现细节。而细节后面我会抽空将自己的一些研究进行整理并发出来。
PS:最近发现脑图真的是一个好东西,方便自己整理和记忆,而且有些只可意会不可言传的都在图中了。
图中的数字标记的是MySQL中执行顺序。
连接器
顾名思义连接器 就是负责服务端处理客户端和服务端的链接。众所周知MySQL是基于TCP来进行命令交互的,而且这些连接都是长连接,所以必须进行管理。如果某个连接长时间处于空闲的状态Server端将主动将这些连接进行关闭,这个时间默认是8小时,可以对wait_time进行设置。这也是为啥在客户端会有复用连接池和设置连接池大小的原因。
连接器同时还会对连接进行用户和权限的检查。
如果全部使用长连接时间累积下来可能会导致内存占用太大,会被系统强行杀掉(OOM),从而导致MySQL异常重启。解决办法可以是定期断开长连接。
查询缓存
在Server会有每次查询的缓存,缓存是以key-value的形式存储的。
连接结束后,默认会进行缓存查询,缓存的key就是客户端发送过来的完整的sql语句,如果命中缓存,就会直接返回结果,不需要往下继续进行了。
虽然缓存的效率会非常高,但是大多数情况下缓存的命中率会非常低,原因是当对一个表进行了更新操作,那么这个表上面的所有查询缓存都会被清空。
可以通过将参数query_cache_type 设置成DEMAND ,这样默认SQL语句不会查询缓存了,而可以使用SQL_CACHE显示指定查询缓存,如下语句:
select SQL_CACHE * from tab;
复制代码
MySQL 8.0版本直接将查询缓存功能删除了!!!! [尴尬的笑了]
分析器
当缓存没有命中,那么SQL语句就会执行到这里了,此时Server会对你的SQL进行解析。
首先做“词法解析”,将所有的“词”识别出来,如select,insert,update等,还有表明,列名等等。识别完成后进行“语法解析”,判读SQL语句是否满足MySQL的语法。一般语法错误会提示第一个出现错误的位置。
优化器
优化器的目的是使查询更加的高效。
优化器的工作会在表里面存在多个索引时选择使用哪个索引;有多表关联时决定各个表的链接顺序。我们通常会在分析一条SQL语句时,使用explain 来查看执行计划,而这里的执行计划就是优化器做的工作。
执行器
执行器是最终真正执行查询的步骤,在经历了分析,优化之后,执行器会以最高效的计划去进行查询。
执行器的第一步是判断该用户是否有查询表的权限,如果没有直接返回错误,如果有就会打开表继续执行。执行器其实是调用对应表的存储引擎所提供的接口来进行查询的。
调用步骤:
- 读取表的第一行,进行条件判断,如果符合就将结果存储到结果集,否则跳过;
- 调用引擎接口读取“下一行”,重复相同的逻辑判断,直到取到表的最后一行;
- 执行器将上述变量过程中所有满足条件的行组成结果集返回给客户端。
对于有索引的表执行的逻辑差不多,第一次调用的都是“满足条件的第一行”的接口,然后循环调用“满足条件的下一行”接口。
执行器每次调用引擎的接口都会使rows_examined字段加1,但是rows_examined 的值和调用次数并不是相等的,因为有时调用引擎的接口会扫描多行的,rows_examined实际是扫描的行数。
存储引擎
我们知道数据真正的是存储在引擎中的,在创建表时可以指定使用哪种引擎。这些引擎都是插件式的,并且具体的细节都是不一样的如MyISAM,InnoDB,MEMORY等。后面会详细介绍这些常用的引擎。下面就简单介绍一下每个引擎的特性。
- MyISAM
它不支持事务,也不支持外键,尤其是访问速度快,对事务完整性没有要求或者以SELECT、INSERT为主的应用基本都可以使用这个引擎来创建表。 - InnoDB
支持事务,外键,一般来说如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择,而且从MySQL 5.5之后的版本都是默认InnoDB引擎。 - MEMORY
数据全部存储于内存,适合数据量小,响应速度快。
以上是对select查询过程的简单分析。不正之处请指正,欢迎留言。
未完待续!!!!!!!