跳到主要内容

SQL 执行流程

一、MySQL 的查询流程

1、查询缓存

sql 作为 key,结果集作为 value 缓存。

被废弃的原因:

  • 命中率低
  • 如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如mysql、information_schema、performance_schema数据库中的表,则不会被缓存
  • 缓存会频繁失效,该表的结构或者数据被修改,如对该表使用了INSERTUPDATEDELETETRUNCATE TABLEALTER TABLEDROP TABLEDROP DATABASE 语句,那使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除。

2、解析器

在解析器中对 SQL 语句进行语法分析、语义分析。

语法树

SQL 词法分析的过程步骤:

3、优化器

在优化器中会确定 SQL 语句的执行路径,比如是根据全表检索,还是根据索引检索等。一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划

逻辑查询优化

逻辑查询优化就是通过改变SQL语句的内容来使得SQL查询更高效,同时为物理查询优化提供更多的候选执行计划。通常采用的方式是对SQL语句进行等价变换,对查询进行重写,而查询重写的数学基础就是关系代数。对条件表达式进行等价谓词重写、条件简化,对视图进行重写,对子查询进行优化,对连接语义进行了外连接消除、嵌套连接消除等。

物理查询优化

物理查询优化是基于关系代数进行的查询重写,而关系代数的每一步都对应着物理计算,这些物理计算往往存在多种算法,因此需要计算各种物理路径的代价,从中选择代价最小的作为执行计划。在这个阶段里,对于单表和多表连接的操作,需要高效地使用索引,提升查询效率。

4、执行器

执行器就会根据表的引擎定义,调用存储引擎API对表进行的读写。存储引擎API只是抽象接口,下面还有个存储引擎层,具体实现还是要看表选择的存储引擎。

二、MySQL 5.7 的 profiles

# 需要在 my.cnf 中设置 query_cache_type = 1 (重启数据库)

select @@profiling;

set @@profiling=1;

select * from user;

show profiles;

show profile for query 1;
show profile cpu, block io for query 1;

三、SQL 语法顺序

from <left_table>
on <join_condition>
<join_type> join <right_table>
where <where_condition>
group bu <group_by_list>
having <having_condition>
select
distinct <select_list>
order by <order_by_condition>
limit <limit_number>

四、Oracle 的 SQL 执行流程

1.语法检查:检查 SQL 拼写是否正确,如果不正确,Oracle 会报语法错误。

2.语义检查:检查 SQL 中的访问对象是否存在。比如我们在写 SELECT 语句的时候,列名写错了,系统就会提示错误。语法检查和语义检查的作用是保证 SQL 语句没有错误。

3.权限检查:看用户是否具备访问该数据的权限。

4.共享池检查:共享池(Shared Pool)是一块内存池,最主要的作用是缓存 SQL 语句和该语句的执行计划。Oracle 通过检查共享池是否存在 SQL 语句的执行计划,来判断进行软解析,还是硬解析。那软解析和硬解析又该怎么理解呢?
在共享池中,Oracle 首先对 SQL 语句进行 Hash 运算 ,然后根据 Hash 值在库缓存(Library Cache)中查找,如果 存在 SQL 语句的执行计划 ,就直接拿来执行,直接进入“执行器”的环节,这就是 软解析
如果没有找到 SQL 语句和执行计划,Oracle 就需要创建解析树进行解析,生成执行计划,进入“优化器”这个步骤,这就是 硬解析

5.优化器:优化器中就是要进行硬解析,也就是决定怎么做,比如创建解析树,生成执行计划。

6.执行器:当有了解析树和执行计划之后,就知道了 SQL 该怎么被执行,这样就可以在执行器中执行语句了。 共享池是 Oracle 中的术语,包括了库缓存,数据字典缓冲区等。我们上面已经讲到了库缓存区,它主要缓存 SQL 语句和执行计划。而 数据字典缓冲区 存储的是 Oracle 中的对象定义,比如表、视图、索引等对象。当对 SQL 语句进行解析的时候,如果需要相关的数据,会从数据字典缓冲区中提取。 库缓存 这一个步骤,决定了 SQL 语句是否需要进行硬解析。为了提升 SQL 的执行效率,我们应该尽量避免硬解析,因为在 SQL 的执行过程中,创建解析树,生成执行计划是很消耗资源的。