mysql的执行的顺序_mysql执行过程以及顺序

前言:mysql在咱们的开发中基本天天都要面对的,做为开发中的数据的来源,mysql承担者存储数据和读写数据的职责。由于学习和了解mysql是相当重要的,那么当咱们在客户端发起一个sql到出现详细的查询数据,这其中究竟经历了什么样的过程?mysql服务端是如何处理请求的,又是如何执行sql语句的?本篇博客未来探讨这个问题:mysql

本篇博客的目录sql

一:mysql执行过程数据库

二:mysql执行过程当中的状态缓存

三:mysql执行的顺序服务器

四:总结函数

一:mysql执行过程性能

mysql总体的执行过程以下图所示:学习

f3260cd037072300e769138d287e7f05.png

1.1:链接器优化

链接器的主要职责就是:spa

①负责与客户端的通讯,是半双工模式,这就意味着某一固定时刻只能由客户端向服务器请求或者服务器向客户端发送数据,而不能同时进行,其中mysql在与客户端链接TC/IP的

②验证请求用户的帐户和密码是否正确,若是帐户和密码错误,会报错:Access denied for user 'root'@'localhost' (using password: YES)

③若是用户的帐户和密码验证经过,会在mysql自带的权限表中查询当前用户的权限:

mysql中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表,mysql权限表的验证过程为:

1:User表:存放用户帐户信息以及全局级别(全部数据库)权限,决定了来自哪些主机的哪些用户能够访问数据库实例Db表:存放数据库级别的权限,决定了来自哪些主机的哪些用户能够访问此数据库Tables_priv表:存放表级别的权限,决定了来自哪些主机的哪些用户能够访问数据库的这个表Columns_priv表:存放列级别的权限,决定了来自哪些主机的哪些用户能够访问数据库表的这个字段Procs_priv表:存放存储过程和函数级别的权限

2:先从user表中的Host,User,Password这3个字段中判断链接的ip、用户名、密码是否存在,存在则经过验证。

3:经过身份认证后,进行权限分配,按照user,db,tables_priv,columns_priv的顺序进行验证。即先检查全局权限表user,若是user中对应的权限为Y,则此用户对全部数据库的权限都为Y,将再也不检查db, tables_priv,columns_priv;若是为N,则到db表中检查此用户对应的具体数据库,并获得db中为Y的权限;若是db中为N,则检查tables_priv中此数据库对应的具体表,取得表中的权限Y,以此类推

4:若是在任何一个过程当中权限验证不经过,都会报错

1.2:缓存

mysql的缓存主要的做用是为了提高查询的效率,缓存以key和value的哈希表形式存储,key是具体的sql语句,value是结果的集合。若是没法命中缓存,就继续走到分析器的的一步,若是命中缓存就直接返回给客户端 。不过须要注意的是在mysql的8.0版本之后,缓存被官方删除掉了。之因此删除掉,是由于查询缓存的失效很是频繁,若是在一个写多读少的环境中,缓存会频繁的新增和失效。对于某些更新压力大的数据库来讲,查询缓存的命中率会很是低,mysql为了维护缓存可能会出现必定的伸缩性的问题,目前在5.6的版本中已经默认关闭了,比较推荐的一种作法是将缓存放在客户端,性能大概会提高5倍左右

1.3:分析器

分析器的主要做用是将客户端发过来的sql语句进行分析,这将包括预处理与解析过程,在这个阶段会解析sql语句的语义,并进行关键词和非关键词进行提取、解析,并组成一个解析树。具体的关键词包括不限定于如下:select/update/delete/or/in/where/group by/having/count/limit等.若是分析到语法错误,会直接给客户端抛出异常:ERROR:You have an error in your SQL syntax.

好比:select *  from user where userId =1234;

在分析器中就经过语义规则器将select from where这些关键词提取和匹配出来,mysql会自动判断关键词和非关键词,将用户的匹配字段和自定义语句识别出来。这个阶段也会作一些校验:好比校验当前数据库是否存在user表,同时假如User表中不存在userId这个字段一样会报错:unknown column in field list.

1.4:优化器

可以进入到优化器阶段表示sql是符合mysql的标准语义规则的而且能够执行的,此阶段主要是进行sql语句的优化,会根据执行计划进行最优的选择,匹配合适的索引,选择最佳的执行方案。好比一个典型的例子是这样的:

表T,对A、B、C列创建联合索引,在进行查询的时候,当sql查询到的结果是:select xx where  B=x and A=x and C=x.不少人会觉得是用不到索引的,但其实会用到,虽然索引必须符合最左原则才能使用,可是本质上,优化器会自动将这条sql优化为:where A=x and B=x and C=X,这种优化会为了底层可以匹配到索引,同时在这个阶段是自动按照执行计划进行预处理,mysql会计算各个执行方法的最佳时间,最终肯定一条执行的sql交给最后的执行器

1.5:执行器

在执行器的阶段,此时会调用存储引擎的API,API会调用存储引擎,主要有一下存储的引擎,不过经常使用的仍是myisam和innodb:

920be1e933a161ced171698043a50775.png

引擎之前的名字叫作:表处理器(其实这个名字我以为更能表达它存在的意义)负责对具体的数据文件进行操做,对sql的语义好比select或者update进行分析,执行具体的操做。在执行完之后会将具体的操做记录到binlog中,须要注意的一点是:select不会记录到binlog中,只有update/delete/insert才会记录到binlog中。而update会采用两阶段提交的方式,记录都redolog中

二:执行的状态

能够经过命令:show full processlist,展现全部的处理进程,主要包含了如下的状态,表示服务器处理客户端的状态,状态包含了从客户端发起请求到后台服务器处理的过程,包括加锁的过程、统计存储引擎的信息,排序数据、搜索中间表、发送数据等。囊括了全部的mysql的全部状态,其中具体的含义以下图:

934996458fa3de30295d607db7483a91.png

三:sql的执行顺序

事实上,sql并非按照咱们的书写顺序来从前日后、左往右依次执行的,它是按照固定的顺序解析的,主要的做用就是从上一个阶段的执行返回结果来提供给下一阶段使用,sql在执行的过程当中会有不一样的临时中间表,通常是按照以下顺序:

fb401a90baba35736c3a8dd3a452e7e8.png

例子: select distinct s.id  from T t join  S s on t.id=s.id where t.name="Yrion" group by t.mobile having count(*)>2  order by s.create_time limit 5;

3.1:from

第一步就是选择出from关键词后面跟的表,这也是sql执行的第一步:表示要从数据库中执行哪张表。

实例说明:在这个例子中就是首先从数据库中找到表T

3.2:join on

join是表示要关联的表,on是链接的条件。经过from和join on选择出须要执行的数据库表T和S,产生笛卡尔积,生成T和S合并的临时中间表Temp1。on:肯定表的绑定关系,经过on产生临时中间表Temp2.

实例说明:找到表S,生成临时中间表Temp1,而后找到表T的id和S的id相同的部分组成成表Temp2,Temp2里面包含着T和Sid相等的全部数据

3.3:where

where表示筛选,根据where后面的条件进行过滤,按照指定的字段的值(若是有and链接符会进行联合筛选)从临时中间表Temp2中筛选须要的数据,注意若是在此阶段找不到数据,会直接返回客户端,不会往下进行.这个过程会生成一个临时中间表Temp3。注意在where中不可使用聚合函数,聚合函数主要是(min\max\count\sum等函数)

实例说明:在temp2临时表集合中找到T表的name="Yrion"的数据,找到数据后会成临时中间表Temp3,temp3里包含name列为"Yrion"的全部表数据

3.4:group by

group by是进行分组,对where条件过滤后的临时表Temp3按照固定的字段进行分组,产生临时中间表Temp4,这个过程只是数据的顺序发生改变,而数据总量不会变化,表中的数据以组的形式存在

实例说明:在temp3表数据中对mobile进行分组,查找出mobile同样的数据,而后放到一块儿,产生temp4临时表。

3.5:Having

对临时中间表Temp4进行聚合,这里能够为count等计数,而后产生中间表Temp5,在此阶段可使用select中的别名

实例说明:在temp4临时表中找出条数大于2的数据,若是小于2直接被舍弃掉,而后生成临时中间表temp5

3.6:select

对分组聚合完的表挑选出须要查询的数据,若是为*会解析为全部数据,此时会产生中间表Temp6

实例说明:在此阶段就是对temp5临时聚合表中S表中的id进行筛选产生Temp6,此时temp6就只包含有s表的id列数据,而且name="Yrion",经过mobile分组数量大于2的数据

3.7:Distinct

distinct对全部的数据进行去重,此时若是有min、max函数会执行字段函数计算,而后产生临时表Temp7

实例说明:此阶段对temp5中的数据进行去重,引擎API会调用去重函数进行数据的过滤,最终只保留id第一次出现的那条数据,而后产生临时中间表temp7

3.8:order by

会根据Temp7进行顺序排列或者逆序排列,而后插入临时中间表Temp8,这个过程比较耗费资源

实例说明:这段会将全部temp7临时表中的数据按照建立时间(create_time)进行排序,这个过程也不会有列或者行损失

3.9:limit

limit对中间表Temp8进行分页,产生临时中间表Temp9,返回给客户端。

实例说明:在temp7中排好序的数据,而后取前五条插入到Temp9这个临时表中,最终返回给客户端

ps:实际上这个过程也并非绝对这样的,中间mysql会有部分的优化以达到最佳的优化效果,好比在select筛选出找到的数据集

四:总结

本篇博客总结了mysql的执行过程,以及sql的执行顺序,理解这些有助于咱们对sql语句进行优化,以及明白mysql中的sql语句从写出来到最终执行的轨迹,有助于咱们对sql有比较深刻和细致的理解,提升咱们的数据库理解能力。同时,对于复杂sql的执行过程、编写都会有必定程度的意义。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值