一. 面试题及剖析
1. 今日面试题
2. 题目剖析
我们继续承接上文,给大家讲解SELECT查询关键字的执行顺序。上一篇文章中,壹哥重点给大家讲解了SELECT语句中各查询关键字的作用及整体执行顺序,如果你没有看过上一篇内容,请移步查阅前文:
高薪程序员&面试题精讲系列81之说一下SQL查询语句的执行顺序详解-作用篇(上)
接下来本文会重点讲解SELECT语句中关键字的执行原理及MySQL架构,从底层来给大家分析SELECT为什么要这样执行,所以今天的内容更重要,请大家认真听课哦。
二. SELECT查询基本使用
在讲解原理之前,我们还是先来回顾一下SELECT查询的基本用法,下面壹哥通过一个基本案例来进行讲解。
1. SELECT查询
这里壹哥是从自己的数据库中,查询商品表,计算商品的平均数量,并按照商品名称进行分组。
SELECT NAME AS '商品名称',AVG(goods_number) AS '平均数量'
FROM weshop_goods
WHERE is_on_sale =1
GROUP BY NAME
HAVING 平均数量 > 40
ORDER BY goods_number DESC
LIMIT 100;
2. 执行结果
上述SQL语句的执行结果如下图所示:
3. 执行顺序
我们把上述SQL语句进行分析,其执行顺序如下:
上面的SELECT执行结果,为什么是这样执行的,底层原理是什么样的?我们现在还不知道,所以接下来壹哥要从MySQL的架构开始,给大家一点点分析其底层原理,重点重点重点,请大家掏出小本本做好笔记。
三. MySQL架构
1. MySQL架构简介
要想深刻地理解掌握SELECT及其他SQL语句的执行,我们有必要先了解一下MySQL数据库的逻辑架构,在此壹哥先把这个架构简单讲解一下,我们先看下图:
上图其实就是MySQL官方给出的MySQL数据库逻辑架构图,从上图可知,MySQL的逻辑架构分为4层:
接下来壹哥把以上分层简单介绍一下。
2. 网络连接层
网络连接层,也可以称之为应用层,这是MySQL逻辑架构中的最上层,主要负责与各客户端进行通信,该层主要执行如下任务:
3. 核心服务层
核心服务层是MySQL Server的核心层,提供了MySQL Server数据库系统的所有逻辑功能,该层包括如下5个核心模块:
这一层,是我们要重点了解的MySQL架构层,所以接下来壹哥会对该层的主要功能进行专门地介绍。
3.1 MySQL Management Server & utilities(系统管理)
该模块提供了丰富的数据库管理功能,包括如下功能:
3.2 SQL Interface(SQL接口)
SQL接口模块主要用来接收用户的SQL命令并对其进行处理,得到用户所需要的结果,具体处理功能如下:
我们平时编写的各种SQL语句,其实就是由这一层来进行语法的规范处理。
3.3 SQL Parser(SQL解析器,重点)
SQL解析器的作用,主要是用来解析SELECT查询语句,最终生成语法树。SQL解析器首先会对查询语句进行语法分析,如果发现SELECT语句语法上有错误,则返回相应的错误信息。语法检查通过后,解析器会先从缓存中查询,如果缓存中有对应的结果,则直接返回缓存结果,就不再进行接下来的优化执行操作了。我们的SELECT查询,其实主要就是在这里进行解析处理,等会壹哥会在第四节中,专门讲解对SELECT查询的解析过程。
3.4 Optimizer(查询优化器)
优化器模块作用主要是对查询语句进行优化,包括选择合适的索引,数据的读取方式等。
3.5 Caches & buffers(缓存)
缓存层包括全局缓存和特定引擎的缓存,用以提高查询效率。如果查询缓存中有命中的查询结果,则查询语句就可以直接从缓存中取数据,无须再通过解析和执行。这个缓存机制是由一系列的小缓存组成的,如表缓存、记录缓存、key缓存、权限缓存等。
4. 存储引擎层
存储引擎是MySQL中与具体文件打交道的子系统,这也是MySQL最有特色的部分。MySQL区别于其他数据库的最重要特点,就是可插拔的存储引擎,提供了多种存储,比如MyISAM、InnoDB、Memory等。
5. 系统文件层
这一层是MySQL的最底层,主要包括MySQL运行时所需的一些系统文件和记录日志,比如redolog、undolog、binlog、errorlog、querylog、slowlog、data、index等,这一层与我们日常的SQL开发联系不大,但我们可以通过修改或查看某些日志文件,来实现某些特殊的功能,或者为数据库优化提供支撑。
四. SELECT语句执行原理(重点)
壹哥已经在上面给大家讲解了SELECT语句的执行顺序,现在我们应该已经掌握了这些内容,但SELECT语句的底层原理到底是什么样的,MySQL对一条SELECT语句到底是怎么处理?这些内容还需要我们进一步的掌握。
1. SELECT执行处理基本流程
我们先来看看下图,该图中所涉及的部分,其实就是上面第三节中SQL Parser(SQL解析器) 部分的职责。
根据上图,壹哥把SELECT查询语句的执行过程简单总结如下:
2. SELECT执行处理原理详解(重点)
接下来,壹哥再把上面的SELECT执行处理的原理详细讲解一下。
2.1 查询缓存
我们操作MySQL数据库时,常用的SQL语句也就是CRUD这四种增删改查语句,而最常用最耗时的肯定是SELECT查询语句。所以为了提高查询效率,MySQL针对查询提供了专门的缓存机制,我们称其为”查询缓存系统“,这也是我们对MySQL进行优化的重要一环。
我们在查询时,会先去缓存中检查一下,看本次查询是否命中了缓存结果。如果命中了,MySQL会立刻返回缓存的结果,直接跳过解析、优化和执行等其余阶段。如果没有命中,则会执行后面的解析、优化和执行等过程,然后再将查询到的完整结构缓存起来供下次使用。
这个缓存系统其实是由一个哈希引用表来进行维护,在这个哈希值中包括了查询本身、当前要查询的数据库、客户端协议版本等一些可能会影响返回结果的信息。并且这个查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生了变化,那么和这个表相关的所有缓存数据都将失效。
这里我们要注意一些可能会导致缓存失效的操作,比如SQL语句中任何字符的不同,例如空格、注解等,都会影响缓存的命中。另外如果查询语句中带有一些不确定的数据时,也不会被缓存。比如SQL语句中包含NOW()、CURRENT_DATE()等系统自带函数、用户自定义函数、存储函数、用户变量、临时表,MySQL数据库中的系统表或者包含任何列级别权限的表,都不会被缓存。
但我们还要注意,当SQL语句中带有不确定函数时,虽然最终并不会命中缓存结果,但依然会对查询缓存进行检查。
另外我们还要注意与查询缓存相关的常用配置项:
2.2 解析和预处理
SQL解析器可以使用MySQL的语法规则对SQL语句进行验证和解析查询,通过关键字将SQL语句进行解析,并生成对应的解析树。
预处理器则会根据MySQL的某些规则进一步检查解析树是否合法,例如检查数据表和数据列是否存在,解析名字和别名,看它们是否有歧义。
2.3 查询优化器
我们编写的每一条SQL语句,其实都可以有多种执行方法,最后都会将相同的结果返回。只不过这些不同的执行方法执行效率有高有低,而查询优化器的作用就是找到其中最好的执行方法。
MySQL默认使用基于成本的查询优化器(Cost-Based Optimizer,CBO),它会尝试预测一个查询语句使用某种执行计划时的成本,并选择其中成本最少的一个。大体的思路就是,CBO会根据统计信息和代价模型(Cost Model)计算每个执行计划的消耗,从中挑选消耗最小的执行计划。
2.4 查询执行引擎
在解析和优化阶段,MySQL会生成与查询对应的执行计划,MySQL的查询执行引擎会根据这个执行计划来完成整个查询。这里的执行计划是一个数据结构,而不是和其他的关系型数据库那样生成对应的字节码。
2.5 返回结果给客户端
当查询完毕,MySQL发现查询结果可以被缓存,那么MySQL就会在这个阶段,将查询到的结果存放到查询缓存中。
然后MySQL会将结果集以增量、逐步返回的方式返回给客户端,也就是在查询生成第一条结果时,MySQL就会开始向客户端逐步返回结果集了。
五. 结语
至此,壹哥就把SQL查询语句的执行顺序,以及SQL查询语句的执行原理给大家做了深入的分析,现在你都掌握了吗?是不是发现,看起来简单的SQL查询,原来竟隐藏着这么多重要的内容。如果你觉得壹哥讲的有些道理,请给壹哥点个赞吧,原创不易,希望大家多多支持!