明天我们就从数据库的角度来思索一下SQL是怎样被执行的。
关于昨天的内容,你会从以下几个方面进行学习:
中的SQL是怎样执行的,哪些是硬解析和软解析;MySQL中的SQL是怎样执行的,MySQL的体系结构又是如何的;哪些是储存引擎,MySQL的储存引擎都有什么?
中的SQL是怎样执行的
我们先来看下SQL在中的执行过程:
从前面这张图中可以看出,SQL句子在中经历了以下的几个步骤。
句型检测:检测SQL拼写是否正确,假若不正确,会报句型错误。语义检测:检测SQL中的访问对象是否存在。例如我们在写句子的时侯,列名弄错了,系统还会提示错误。句型检测和语义检测的作用是保证SQL句子没有错误。权限检测:看用户是否具备访问该数据的权限。共享池检测:共享池(Pool)是一块显存池,最主要的作用是缓存SQL句子和该句子的执行计划。通过检测共享池是否存在SQL句子的执行计划,来判定进行软解析,还是硬解析。那软解析和硬解析又该如何理解呢?
在共享池中,首先对SQL句子进行Hash运算,之后按照Hash值在库缓存(Cache)中查找,假如存在SQL句子的执行计划,就直接用来执行,直接步入“执行器”的环节,这就是软解析。
假如没有找到SQL句子和执行计划,就须要创建解析树进行解析,生成执行计划,步入“优化器”这个步骤,这就是硬解析。
优化器:优化器中就是要进行硬解析,也就是决定如何做,例如创建解析树,生成执行计划。执行器:当有了解析树和执行计划以后,就晓得了SQL该如何被执行,这样就可以在执行器中执行句子了。
共享池是中的术语,包括了库缓存,数据字典缓冲区等。我们里面早已提到了库缓存区,它主要缓存SQL句子和执行计划。而数据字典缓冲区储存的是中的对象定义,例如表、视图、索引等对象。当对SQL句子进行解析的时侯,假如须要相关的数据,会从数据字典缓冲区中提取。
库缓存这一个步骤,决定了SQL句子是否须要进行硬解析。为了提高SQL的执行效率,我们应当尽量避开硬解析,由于在SQL的执行过程中,创建解析树,生成执行计划是很消耗资源的。
你可能会问,怎么避开硬解析,尽量使用软解析呢?在中,绑定变量是它的一大特色。绑定变量就是在SQL句子中使用变量,通过不同的变量取值来改变SQL的执行结果。这样做的益处是能提高软解析的可能性,不足之处在于可能会造成生成的执行计划不够优化,因而是否须要绑定变量还须要视情况而定。
举个反例,我们可以使用下边的查询句子:
SQL>*fromwhere=10001;
你也可以使用绑定变量,如:
SQL>*fromwhere=:;
这两个查询句子的效率在中是完全不同的。假如你在查询=10001以后,就会查询10002、10003之类的数据,这么每一次查询还会创建一个新的查询解析。而第二种方法使用了绑定变量,这么在第一次查询以后,在共享池中都会存在这类查询的执行计划,也就是软解析。
因而我们可以通过使用绑定变量来降低硬解析,降低的解析工作量。并且这些方法也有缺点,使用动态SQL的形式,由于参数不同,会造成SQL的执行效率不同,同时SQL优化也会比较困难。
MySQL中的SQL是怎样执行的
中采用了共享池来判定SQL句子是否存在缓存和执行计划,通过这一步骤我们可以晓得应当采用硬解析还是软解析。这么在MySQL中,SQL是怎样被执行的呢?
首先MySQL是典型的C/S构架,即/构架,服务器端程序使用的。整体的MySQL流程如右图所示:
你能看见MySQL由三层组成:
联接层:顾客端和服务器端构建联接,顾客端发送SQL至服务器端;SQL层:对SQL句子进行查询处理;储存引擎层:与数据库文件打交道,负责数据的储存和读取。
其中SQL层与数据库文件的储存形式无关,我们来看下SQL层的结构:
查询缓存:假如在查询缓存中发觉了这条SQL句子,都会直接将结果返回给顾客端;假如没有,就步入到解析器阶段。须要说明的是,由于查询缓存常常效率不高,所以在.0以后就抛弃了这个功能。解析器:在解析器中对SQL句子进行句型剖析、语义剖析。优化器:在优化器中会确定SQL句子的执行路径,例如是按照全表检索,还是按照索引来检索等。执行器:在执行之前须要判定该用户是否具备权限,假如具备权限就执行SQL查询并返回结果。在.0以下的版本,假如设置了查询缓存,这时会将查询结果进行缓存。
你能看见SQL句子在MySQL中的流程是:SQL句子→缓存查询→解析器→优化器→执行器。在一部份中,MySQL和执行SQL的原理是一样的。
与不同的是,MySQL的储存引擎采用了插件的方式,每位储存引擎都面向一种特定的数据库应用环境。同时开源的MySQL还容许开发人员设置自己的储存引擎,下边是一些常见的储存引擎:
储存引擎:它是MySQL5.5版本以后默认的储存引擎,最大的特征是支持事务、行级锁定、外键约束等。储存引擎:在MySQL5.5版本之前是默认的储存引擎,不支持事务,也不支持字段,最大的特征是速率快,占用资源少。储存引擎:使用系统显存作为储存介质,便于得到更快的响应速率。不过若果进程崩溃,则会造成所有的数据遗失,因而我们只有当数据是临时的情况下才使用储存引擎。NDB储存引擎:也称作NDB储存引擎,主要用于MySQL分布式集群环境,类似于的RAC集群。储存引擎:它有挺好的压缩机制,用于文件归档,在恳求写入时会进行压缩,所以也常常拿来做库房。
须要注意的是,数据库的设计在于表的设计,而在MySQL中每位表的设计都可以采用不同的储存引擎,我们可以按照实际的数据处理须要来选择储存引擎,这也是MySQL的强悍之处。
数据库管理系统也是一种软件
我们刚刚了解了SQL句子在和MySQL中的执行流程,实际上完整的和MySQL结布光要复杂得多:
假如你只是简单地把MySQL和看成数据库管理系统软件,从外部看难免会认为“晦涩难懂”,虽然组织结构太多了。我们在学习的时侯,还须要具备具象的能力,抓取最核心的部份:SQL的执行原理。由于不同的DBMS的SQL的执行原理是相通的,只是在不同的软件中,各有各的实现路径。
既然一条SQL句子会经历不同的模块,那我们就来看下,在不同的模块中,SQL执行所使用的资源(时间)是如何的。下边我来教你怎样在MySQL中对一条SQL句子的执行时间进行剖析。
首先我们须要看下是否开启,开启它可以让MySQL搜集在SQL执行时所使用的资源情况,命令如下:
mysql>@@;
=0代表关掉,我们须要把打开,即设置为1:
mysql>set=1;
之后我们执行一个SQL查询(你可以执行任何一个SQL查询):
mysql>*fromwucai.heros;
查看当前会话所形成的所有,你会发觉我们刚刚执行了两次查询,QueryID分别为1和2。假如我们想要获取上一次查询的执行时间,可以使用:
mysql>show;
其实你也可以查询指定的QueryID,例如:
mysql>showforquery2;
查询SQL的执行时间结果和前面是一样的。
在8.0版本以后,MySQL不再支持缓存的查询,缘由我在上文早已说过。一旦数据表有更新,缓存都将清空,因而只有数据表是静态的时侯,或则数据表极少发生变化时,使用缓存查询才有价值,否则假如数据表常常更新,反倒降低了SQL的查询时间。
你可以使用()来查看MySQL的版本情况。
总结
我们在使用SQL的时侯,常常只见行道树,不见森林,不会注意到它在各类数据库软件中是怎样执行的,明天我们从概貌的角度来理解这个问题。你能看见不同的RDBMS之间有相同的地方,也有不同的地方。
相同的地方在于和MySQL都是通过解析器→优化器→执行器这样的流程来执行SQL的。
但和MySQL在进行SQL的查询里面有软件实现层面的差别。提出了共享池的概念,通过共享池来判定是进行软解析,还是硬解析。而在MySQL中,8.0之后的版本不再支持查询缓存,而是直接执行解析器→优化器→执行器的流程,这一点从MySQL中的show里也能见到。同时MySQL的一大特色就是提供了各类储存引擎以供选择,不同的储存引擎有各自的使用场景,我们可以针对每张表选择适宜的储存引擎。
明天的内容到这儿就结束了,你能说一下中的绑定变量是哪些吗?使用它有哪些异同点吗?MySQL的储存引擎是一大特色,其中和都是常用的储存引擎,这两个搜索引擎的特点和使用场景分别是哪些?
最后留一道选择题吧,解析后的SQL句子在的那个区域中进行缓存?
A.数据缓冲区
B.日志缓冲区
C.共享池
D.大池
假如这篇文章帮你理顺了和MySQL执行SQL的过程,欢迎你把它分享给你的同事或则同学。