一条 SQL 查询语句是如何执行的

MySQL 数据库内部结构图

mysql内部结构图
图片来源:极客时间 MySQL45 讲中第一节

连接器 : 管理客户端与 server 层的连接,对权限进行验证。
查询缓存: 保存着缓存数据
分析器: 词法分析、语法分析
优化器: 生成执行计划,对索引的选择
执行器: 操作引擎,返回结果集
存储引擎: 各种不同的存储引擎,保存数据,提供着读写接口

引擎的选择

  • 在MySQL中,引擎默认是 Inodb 的,在 MySQL5.5 版本以后就是默认的引擎。在 MySQL 中是提供着插件式的,如果想更换存储引擎,可以在建表的时候使用下面的语句 ENGINE=MyISAM 来指定引擎的选择。如下面的代码:
    1
    2
    3
    4
    CREATE TABLE `spacedong`.`test` (
    )
    ENGINE = MyISAM
    COMMENT = '测试';

连接器

  • 连接器就是一个连接着客户端和 Server 层的部件,在这个部件下,会对连接的账号和密码进行验证,同时对这个账号密码的权限验证。
    • 注意点,在管理员为这个连接账号进行了权限的更改后,需要重新连接后,这个权限才能生效。
  • show processlist 命令
    • show processlist 命令是一个查询数据库中的连接进程命令,这个命令可以看到关于数据库中的连接器状态和数量。这个命令可以看到关于空闲连接等,如下图:

image

  • 如果客户端的空闲连接太久没有动作,那么就会自动断开连接。时间是默认的 8 个小时,由参数 wait_timeout 来控制的。wait_timeout 参数和 connection_timeout 参数这两者的区别如下:

wait_timeout: 连接完成后,使用的过程中的等待时间
connection_timeout: 连接过程中等待的时间

  • 在连接器中怎样给新的连接归类为长连接还是短连接的,判断的标准是什么?
    • 答:当客户端连接成功后,连接就是连接,断开就是断开,建议的是减少创建连接的次数。
  • 连接的过程中消耗的内存是怎么管理的,或者是在优化连接的时候,怎样在通过内存的大小来判断关于这个连接是小内存还是大内存,从而是否选择mysql_reset_connection来初始化连接资源。

查询缓存

在连接成功后就到查询缓存的步骤了:先是去缓存里面查找是否有关于这条查询语句的的结果,如果在之前查找果这条语句,那么就会把查询的结果来当做 Value ,查询的这条语句当做 Key 来以 K-V 对的形式保存在缓存中。

  • 查询缓存的弊端:只要有一张表进行了更新,那么就会导致整张表的查询缓存失效,在频繁更新的表上,
  • 查询缓存的使用场景:适合静态的表,一些数据不会改变的表就可以用查询缓存来查询。
  • 在 MySQL 中可以把参数 query_cache_type 设置成 DEMAND,这样就是默认了查询的时候是没有使用缓存的,可以显示开始缓存

    1
    select SQL_CACHE * from T
  • MySQL 8.0 直接删除了查询缓存的模块了。

分析器

在查询缓存模块如果找不到数据,那么这个执行语句就会到执行器这个模块。

  • 词法分析:对这个 sql 语句进行识别,识别出来是 select 还是 insert 等语句。
  • 语法分析:对这个 sql 语句进行语法分析,判断这个语句是否是会出现语法错误等。

优化器

  • 当一个 SQL 语句中有多个索引的时候,这个时候会在优化器中判断,哪个索引的选择效率会更高,然后选择哪个。或者是当一个查询的时候会有多种选择方案,会选择效率最高的那个。
  • 优化器阶段过后,这个时候就已经生成了执行计划了,接着就到执行器了。

执行器

等优化器分析结果出来后,就会传到执行器,这个时候执行器开始执行,执行前的第一步,先是进行检查要执行的 sql 语句中的表有没有权限。没有权限的话会抛出异常。

  • 如果有权限,那么就是打开表,开始对满足条件的行数开始扫描,直到找到符合条件的那条数据。

小结

以上就是关于sql语句是如何执行的过程的,里面还有很多的细节没有涉及的,所以接下来的文章会逐渐来讲解这个!

参看资料:

极客时间 MySQL45 讲:

基础架构:一条SQL查询语句是如何执行的?

spacedong wechat
愿意交个朋友吗~
觉得有收获么