大家好!这是我的第一篇文章。
这篇文章我将介绍一条sql查询语句是如何执行的
下面是MySQL架构图:
总的来说,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命令查看:
如果客户端长时间处于不活动状态,连接器将自动断开连接。持续时间由 wait_timeout 参数控制,默认为 8 小时。
如果连接终止并且客户端发送请求,则会收到错误消息:在查询期间丢失与 MySQL 服务器的连接。要继续,您需要重新连接,然后执行请求。
在数据库中,持久连接是指客户端在成功连接后为连续请求保持相同的连接。短连接是指在几次查询后断开连接并重新连接以进行后续查询。
由于连接过程比较复杂,建议开发过程中尽量减少连接的创建,即尽可能使用持久连接。
但是,当使用持久连接时,MySQL 的内存使用量可能会显着增加,因为执行期间使用的临时内存是在连接对象内管理的。仅当连接终止时,这些资源才会被释放。如果长连接不断累积,可能会导致内存使用过多,导致系统强行终止MySQL(OOM),导致意外重启。
解决方案:
注意:从 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 列上没有索引。执行者的执行过程如下:
至此,查询完成。
对于索引表,该过程涉及使用引擎的预定义方法来迭代获取“第一个匹配行”和“下一个匹配行”。
慢查询日志中,rows_examined字段表示查询执行过程中扫描的行数。每次执行器调用引擎检索数据行时,该值都会累加。
在某些情况下,对执行器的单次调用可能涉及在引擎内部扫描多行。因此,引擎扫描的行数不一定等于 rows_examined.
感谢您的阅读!希望文章对您有所帮助。
以上是SQL查询语句是如何执行的的详细内容。更多信息请关注PHP中文网其他相关文章!