数据库中的sql语句写入语句的操作流程及解析

xzdxmynet 发布于 2024-02-06 阅读(57)

开发者基本都知道我们的数据存在于数据库中(目前最常见的是mysql和MySQL,由于笔者比较擅长mysql,所以这里默认的数据库是mysql)。 服务器通过sql语句查询数据的请求传递到mysql数据库。 数据库获取到sql语句后。 进行了哪些操作? 在这里我想向大家介绍一下我个人的理解。 欢迎大家在评论区批评指正。

流程概览

mysql获取到sql语句后,大致流程如下:

1.SQL解析器:负责解析和转发SQL

2. 预处理器:验证解析后的sql树

3.查询优化器:获取执行计划

4.查询执行引擎:获取数据结果集

5. 将数据返回给调用端。

流程图如下:

分发器和缓存阶段

首先,如果系统的缓存功能开启,那么SQL语句进入mysql后,SQL会判断是否是关键字。 如果有,那么首先去查询缓存中查询。 如果该sql语句在查询缓存中能够命中,则直接返回查询缓存中该查询语句对应的值(在缓存中,对查询语句进行哈希运算,结果作为key值,查询结果集是值)。

如果命中缓存的话,查询速度还是相当快的。 但查询缓存也有其相应的缺点。

首先,如果开启缓存,服务器会消耗大量的内存空间; 其次,缓存有时不适用; 最后,在某些情况下,开启缓存不会将相应的SQL语句写入缓存中。

不适用缓存的情况:

缓存锁比较强,对动态SQL的支持不够。

当数据更新时,缓存执行表级锁。 更新完成后,所有与更新内容相关的缓存都会被删除。 因此,如果对表的写入次数很多,缓存就很浪费性能。 如果写入量很大,缓存实际上可能会导致mysql变慢。

当无法查询缓存时:

1、查询条件包含不确定的数据:比如now等。

2. 缓存区分大小写。 例如*和*FROM test不会被解析成同一个sql。

查询带来的额外开销:

1.开始之前需要检查缓存是否命中。

2、输出结果时,需要进行额外的数据缓存操作。

3、写入数据时,mysql会将对应表的所有缓存设置为无效。 当缓存内存较大时,会造成较大的系统消耗。

SQL 解析器和预处理

sql解析器在命令分发后将相应的sql语句解析成sql解析树。 sql解析树是Mysql本身内部的语法规则和解析查询。 验证是否使用了错误的关键字、SQL语法顺序是否正确等(语法错误)

解析完成后,对查询语句进行预处理,根据mysql的规则检查解析树是否合法。 (表是否存在,别名是否有歧义等)

查询优化器

查询优化器获取执行计划,然后查询执行引擎执行相应的操作。 查询优化器是数据库l的核心模块,分为cbo和rbo两种类型。

其中,rbo是基于规则的优化器。 (早期版本使用了rbo,现在保留,但默认是cbo。Mysql没有rbo优化器)

这些规则被硬编码在数据库的代码中。 rbo会使用输入的sql语句能够匹配的最高优先级规则作为执行计划。 例如:rbo中有这样一条规则:如果有索引,就使用索引。 那么所有有索引的表在执行时都会被索引。 rbo最大的问题是执行计划是由固定的规则决定的。 它没有考虑sql涉及的对象的数量和分布。 所选择的规则有可能不是最优的执行计划。

cbo是一个基于成本的优化器(基于统计信息),它从众多目标执行路径中选择成本最低的执行路径作为执行计划。 cost是指mysql根据相关统计信息计算出的sql语句对应的io、cpu等消耗的预估。 计算过程涉及索引、表、行等数据,过程相对复杂。

1.查询优化器使用统计信息来选择sql的执行计划。

2、Mysql没有数据柱状图,统计信息无法手动删除。 (有)

3、服务器上有查询优化器,但没有保存数据和索引统计信息。 统计信息由存储引擎实现,不同的存储引擎存储不同的统计信息。

4、统计信息分为索引统计信息和表统计信息。

查看统计数据

指数统计

或.表

表统计

或.表

查询执行引擎+返回数据给客户端

获取到执行计划后,根据已有的执行计划,查询执行引擎,mysql的SQL Layer层,调用Layer层的接口,从mysql的存储引擎中获取对应的结果集,然后返回给用户。

执行完成后,将结果返回给客户端。 如果是查询语句并且启用了缓存,那么MySQL会同时将结果集放入查询缓存中。 然后返回找到的结果集。 如果是增删改操作,则返回执行该语句后受影响的行数。

标签:  缓存 查询 语句 解析 统计 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。