zoukankan      html  css  js  c++  java
  • 一条查询语句在MySQL中是如何执行的?

    前言

    我们在学习一种技术的时候,首先要鸟瞰其全貌,千万不要一开始就陷入到细节中去,这样有助于我们站在高维度其理解问题 —— 丁奇。

    学习MySQL也是一样,所以我们可以从一条查询语句的执行开始看起。

    select * from t where id = 1;

    通常情况下,我们在使用MySQL的时候,只是从客户端输入一行指令,然后获取一个返回结果。
    但是对于一个开发人员来说,只知道这些是远远不够的,我们还需要知道这句指令背后的执行流程,便于排查问题。

    MySQL逻辑架构

    这里还是引用丁奇老师的MySQL系统结构图:

     
    mysql的逻辑架构图

    MySQL可以分为Service层和存储引擎层两部分。

    • Service层又可分为:连接器、查询缓存、分析器、优化器、执行器。在MySQL中,跨存储引擎层的的功能都在这一层实现,如日期函数、存储过程、视图等。
    • 存储引擎层负责数据的存储和提取,是一个插件式的结构,一个Service可以对应多个存储引擎。常见的存储引擎有:InnoDB、MyISAM、Memory等。

    连接器

    连接器负责客户端与Mysql服务器的建立连接、获取权限、管理连接。连接命令一般是这么写的:

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

    如果用户名和密码校验通过后,连接器就会从权限表中查到该用户的权限。后续当该用户执行操作的时候,依赖的都是这个时候读取到的权限。

    创建连接后,我们就可以使用 show processlist查看该连接:

     
    show processlist的执行结果


    如果客户端在一段时间没用任何指令,那么这个连接就会被断开。这个参数是wait_timeout,默认时间为8小时。
    这里还涉及到一个概念, 长连接和短连接 。

    • 长连接:建立连接后,如果客户端持续有请求,则一直使用同一个连接。
    • 短连接:指执行完很少的指令,连接就断开了,如果有后续的指令,就需要重新建立连接。

    建立连接的过程是相对复杂的,所以我们应该避免短连接,那是不是连接越长越好?也不是这样。MySQL在执行过程中使用的内存是管理在连接中的,这些资源资源会在断开连接的时候才会被释放。如果一直得不到释放,就会有OOM的问题,表现出来的现象就是MySQL异常重启了。

    • 所以我们需要定时的断开长连接,或者是判断执行过一个占用内存的大查询后,断开连接。
    • 如果是Mysql 5.7版本后,可以在执行一个大操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。

    查询缓存

    通常情况下我们不会启用查询缓存,因为这个缓存命中率不高,每次对表的更新,都会清空缓存。在MySQL8.0后的版本被移除。

    分析器

    MySQL中的分析器,主要有两个作用,分别是词法分析和语法分析。词法分析的作用是将SQL语句将我们的数据库结构相对应,比如将字符t对应成表T,将字符id对应表中的id列。

    select * from t where id = 1;

    语法分析做的是检测我们输入的命令是否符合MySQL语法,如果语句不对,则会有相应的提示,便于我们去修改:

    语法分析

    优化器

    经过了分析器,MySQL已经知道了我们想做什么了,接下来就该是怎么做。
    比如在有多个索引的时候,选择哪个索引可以减少扫描数据的行数。进行多表联合查询的时候,哪张表作为驱动表,会减少扫描数据的行数等。

    执行器

    执行器的工作就是执行语句,但是在执行之前,会先判断该用户的权限,只有通过了权限认证,才可以执行语句。如果该用户有权限,执行器会打开表,调用相应存储引擎的接口,而存储引擎接口负责将数据存入结果集中返回给客户端。

    小结

    以上就是一条查询语句在MySQL中的执行过程,这对我们理解MySQL的执行过程,进行数据库调优是十分重要的。

  • 相关阅读:
    分布式任务框架elastic-job 学习笔记
    spring 基础知识复习
    Spring MVC 搭建
    python引入自定义模块
    python操作Excel读写--使用xlrd
    selenium2.0关于python的常用函数
    从零开始学Python07作业源码:虚拟人生(仅供参考)
    通过System.getProperties()获取系统参数
    Android Studio启动后出现cannot bind to 127.0.0.1:5037 10048的解决办法
    开发环境入门 linux基础 (部分)awk 赋值变量 if
  • 原文地址:https://www.cnblogs.com/nedulee/p/11832005.html
Copyright © 2011-2022 走看看