首页 >数据库 >mysql教程 >SQL查询语句是如何执行的

SQL查询语句是如何执行的

DDD
DDD原创
2025-01-01 05:49:27926浏览

大家好!这是我的第一篇文章。

这篇文章我将介绍一条sql查询语句是如何执行的

下面是MySQL架构图:

How is an SQL Query Statement executed

总的来说,MySQl可以分为两部分:服务器层和存储引擎层。

服务器层包括连接器、查询缓存、解析器、优化器、执行器等,包含MySQL的大部分核心服务功能,以及所有内置功能(如日期、时间、数学和加密)功能)。所有跨存储引擎的功能,例如存储过程、触发器和视图都在这一层实现。

存储引擎层负责数据的存储和检索。其架构是基于插件的,支持InnoDB、MyISAM、Memory等多种存储引擎。从MySQL 5.5.5开始,InnoDB成为MySQL的默认存储引擎。

创建表时可以使用带有engine=memory的create table语句指定内存引擎。

不同的存储引擎共享同一个Server层

连接器

第一步是连接数据库,这需要连接器。连接器负责与客户端建立连接、获取权限并维护和管理连接。连接命令为:

mysql -h$ip -P$port -u$user -p

该命令用于与服务器建立连接。完成经典的 TCP 握手后,连接器将使用提供商的用户名和密码来验证您的身份。

  • 如果用户名或密码不正确,您将收到“用户错误导致访问被拒绝”的消息,并且客户端程序将终止。
  • 如果身份验证成功,连接器将从权限表中检索当前帐户的权限。此连接期间的所有权限检查都依赖于此初始检索。

这意味着一旦连接成功建立,管理员对用户权限所做的任何更改都不会影响现有连接的权限。只有新连接才会使用更新后的权限设置。

连接建立后,如果没有后续动作,则连接进入空闲状态,可以使用show processlist命令查看:

How is an SQL Query Statement executed

如果客户端长时间处于不活动状态,连接器将自动断开连接。持续时间由 wait_timeout 参数控制,默认为 8 小时。

如果连接终止并且客户端发送请求,则会收到错误消息:在查询期间丢失与 MySQL 服务器的连接。要继续,您需要重新连接,然后执行请求。

在数据库中,持久连接是指客户端在成功连接后为连续请求保持相同的连接。短连接是指在几次查询后断开连接并重新连接以进行后续查询。

由于连接过程比较复杂,建议开发过程中尽量减少连接的创建,即尽可能使用持久连接。

但是,当使用持久连接时,MySQL 的内存使用量可能会显着增加,因为执行期间使用的临时内存是在连接对象内管理的。仅当连接终止时,这些资源才会被释放。如果长连接不断累积,可能会导致内存使用过多,导致系统强行终止MySQL(OOM),导致意外重启。

解决方案

  1. 定期断开持久连接。使用连接一段时间或执行消耗过多内存的查询后,请断开连接并重新连接以进行后续查询。
  2. 如果您使用的是 MySQL 5.7 或更高版本,您可以在执行资源密集型操作后使用 mysql_reset_connection 来重新初始化连接资源。此过程不需要重新连接或重新验证,而是将连接重置为刚刚创建的状态。

查询缓存

注意:从 MySQL 8.0 开始,查询缓存功能已被完全删除,因为其弊大于利

当MySQL收到查询请求时,它首先检查查询缓存,看看这个查询之前是否已经执行过。之前执行过的查询及其结果以键值对的形式缓存在内存中。键是查询语句,值是结果。如果在查询缓存中找到该键,则将该值直接返回给客户端。

如果在查询缓存中未找到查询,则过程继续。

为什么查询缓存弊大于利?

查询缓存失效的情况非常频繁地发生。对表的任何更新都会清除与该表相关的所有查询缓存,导致缓存命中率非常低,除非该表是静态配置表。

MySQL提供了一种“按需”的方法来使用查询缓存。通过将参数query_cache_type设置为DEMAND,SQL语句默认不会使用查询缓存。要使用查询缓存,可以显式指定 SQL_CACHE:

mysql -h$ip -P$port -u$user -p

解析器

如果查询缓存没有命中,则语句执行过程开始。 MySQL 首先需要了解要做什么,因此它会解析 SQL 语句。

解析器首先执行词法分析。输入的 SQL 语句由字符串和空格组成,MySQL 会对其进行分析,以识别每个部分代表的含义。例如select标识为查询语句,T标识为表名,ID标识为列。

词法分析之后,进行语法分析。语法分析器根据词法分析的结果判断SQL语句是否符合MySQL的语法规则。

如果存在语法错误,将会显示类似“您的 SQL 语法有错误”的错误消息。例如,在以下查询中,select 关键字拼写错误:

select SQL_CACHE * from T where ID=10;

优化器

解析之后,MySQL 知道你想做什么。接下来,优化器确定如何执行。

当一个表有多个索引时,优化器决定使用哪个索引,或者当查询涉及多个表时,优化器决定表连接的顺序。例如,在以下查询中:

mysql> elect * from t where ID=1;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1

查询可以从检索 t1 或 t2 中的值开始。两种方法产生相同的逻辑结果,但它们的性能可能不同。优化器的作用是选择最有效的计划。

优化阶段结束后,流程进入执行器。

执行者

执行器开始执行查询。

执行前,首先检查当前连接是否有查询表的权限。如果没有,则返回错误,指示权限不足。 (从查询缓存返回结果时也会执行权限检查。)

如果授予权限,则打开表并继续执行。在此过程中,执行器根据表的引擎定义与存储引擎进行交互。

例如,假设表 T 在 ID 列上没有索引。执行者的执行过程如下:

  1. 调用InnoDB引擎接口取出表的第一行,检查ID值是否为10,如果不是则跳过;如果是,则将其添加到结果集中。
  2. 调用引擎接口获取“下一行”,重复相同的逻辑,直到检查完所有行。
  3. 执行器将累积的结果集返回给客户端。

至此,查询完成。

对于索引表,该过程涉及使用引擎的预定义方法来迭代获取“第一个匹配行”和“下一个匹配行”。

慢查询日志中,rows_examined字段表示查询执行过程中扫描的行数。每次执行器调用引擎检索数据行时,该值都会累加。

在某些情况下,对执行器的单次调用可能涉及在引擎内部扫描多行。因此,引擎扫描的行数不一定等于 rows_examined.

结尾

感谢您的阅读!希望文章对您有所帮助。

以上是SQL查询语句是如何执行的的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn