当前位置:网站首页>mysql - sql执行过程
mysql - sql执行过程
2022-06-22 14:38:00 【炸了毛的猫】
一、组件介绍
1、连接器
1)负责与客户端的通信,是半双工模式,这就意味着某一固定时刻只能由客户端向服务器请求或者服务器向客户端发送数据,而不能同时进行。
2)验证用户名和密码是否正确(数据库mysql的user表中进行验证),如果错误返回错误通知(deAcess nied for user ‘root’@‘localhost’(using password:YES)),如果正确,则会去 mysql 的权限表(mysql中的 user、db、columns_priv、Host 表,分别存储的是全局级别、数据库级别、表级别、列级别、配合 db 的数据库级别)查询当前用户的权限。
2、缓存(Cache)
也称为查询缓存,存储的数据是以键值对的形式进行存储,如果开启了缓存,那么在一条查询sql语句进来时会先判断缓存中是否包含当前的sql语句键值对,如果存在直接将其对应的结果返回,如果不存在再执行后面一系列操作。如果没有开启则直接跳过。
3、分析器
对客户端传来的 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.
4、优化器
进入优化器说明sql语句是符合标准语义规则并且可以执行。优化器会根据执行计划选择最优的选择,匹配合适的索引,选择最佳的方案。比如一个典型的例子是这样的:
表T,对A、B、C列建立联合索引(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交给最后的执行器。
优化器会根据扫描行数、是否使用临时表、是否排序等来判断是否使用某个索引,其中扫描行数的计算可以通过统计信息来估算得出,而统计信息可以看作是索引唯一数的数量,可以使用部分采样来估算,具体就是选择 N 个数据页,统计这些页上数据的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了。但是因为索引数据会变化,所以索引的统计信息也会变化。当变更的数据行数超过 1/M 的时候,就会重新计算一次统计信息。
5、执行器
执行器会调用对应的存储引擎执行 sql。主流的是MyISAM 和 Innodb。
MyISAM 和 Innodb 的索引数据结构是B+树
memory索引数据结构是 hash表

二、执行过程
1、写操作

2、读操作
查询的过程和更新比较相似,但是有些不同,主要是来源于他们在查找筛选时的不同,更新因为在查找后会进行更新操作,所以查询这一行为至始至终都在缓冲池中(使用到索引且缓冲池中包含数据对应的数据页)。而查询则更复杂一些。
创建表:
create table tbl_test (a int primary key, b int, c int, d int, e varchar(50));
create index idx_bcd on tbl_test(b, c, d);
insert into tbl_test values (4,3,1,1,'a');
insert into tbl_test values (1,1,1,2,'d');
insert into tbl_test values (8,8,7,8,'h');
insert into tbl_test values (2,2,1,2,'g');
insert into tbl_test values (5,2,2,5,'e');
insert into tbl_test values (3,3,2,1,'c');
insert into tbl_test values (7,4,0,5,'b');
insert into tbl_test values (6,5,2,4,'f');
在执行 select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != ‘a’; 在提取时,会将 Where 条件拆分为 Index Key(First Key & Last Key)、Index Filter 与 Table Filter。
1、Index Key
用于确定 SQL 查询在索引中的连续范围(起始点 + 终止点)的查询条件,被称之为Index Key;由于一个范围,至少包含一个起始条件与一个终止条件,因此 Index Key 也被拆分为 Index First Key 和 Index Last Key,分别用于定位索引查找的起始点以终止点。
Index First Key
用于确定索引查询范围的起始点;提取规则:从索引的第一个键值开始,检查其在 where 条件中是否存在,若存在并且条件是=、>=,则将对应的条件加入Index First Key之中,继续读取索引的下一个键值,使用同样的提取规则;若存在并且条件是 >,则将对应的条件加入 Index First Key 中,同时终止 Index First Key 的提取;若不存在,同样终止 Index First Key 的提取。
针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != ‘a’,应用这个提取规则,提取出来的 Index First Key 为 b >= 2, c > 0 ,由于 c 的条件为 >,提取结束
Index Last Key
用于确定索引查询范围的终止点,与 Index First Key 正好相反;提取规则:从索引的第一个键值开始,检查其在 where 条件中是否存在,若存在并且条件是 =、<=,则将对应条件加入到 Index Last Key 中,继续提取索引的下一个键值,使用同样的提取规则;若存在并且条件是 < ,则将条件加入到 Index Last Key 中,同时终止提取;若不存在,同样终止Index Last Key的提取
针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != ‘a’,应用这个提取规则,提取出来的 Index Last Key为 b < 7 ,由于是 < 符号,提取结束
2、Index Filter
在完成 Index Key 的提取之后,我们根据 where 条件固定了索引的查询范围,那么是不是在范围内的每一个索引项都满足 WHERE 条件了 ? 很明显 4,0,5 , 2,1,2 均属于范围中,但是又均不满足SQL 的查询条件
所以 Index Filter 用于索引范围确定后,确定 SQL 中还有哪些条件可以使用索引来过滤;提取规则:从索引列的第一列开始,检查其在 where 条件中是否存在,若存在并且 where 条件仅为 =,则跳过第一列继续检查索引下一列,下一索引列采取与索引第一列同样的提取规则;若 where 条件为 >=、>、<、<= 其中的几种,则跳过索引第一列,将其余 where 条件中索引相关列全部加入到 Index Filter 之中;若索引第一列的 where 条件包含 =、>=、>、<、<= 之外的条件,则将此条件以及其余 where 条件中索引相关列全部加入到 Index Filter 之中;若第一列不包含查询条件,则将所有索引相关条件均加入到 Index Filter之中
针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != ‘a’,应用这个提取规则,提取出来的 Index Filter 为 c > 0 and d != 2 ,因为索引第一列只包含 >=、< 两个条件,因此第一列跳过,将余下的 c、d 两列加入到 Index Filter 中,提取结束
3、Table Filter
这个就比较简单了,where 中不能被索引过滤的条件都归为此中;提取规则:所有不属于索引列的查询条件,均归为 Table Filter 之中
针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != ‘a’,应用这个提取规则,那么 Table Filter 就为 e != ‘a’
在5.6 之前,是不分 Table Filter 与 Index Filter 的,这两个条件都直接分配到 Server 层进行筛选。筛选过程是先根据 Index Key 的条件先在引擎层进行初步筛选,然后得到对应的主键值进行回表查询得到初筛的行记录,传入 Server 层进行后续的筛选,在 Server 层的筛选因为没有用到索引所以会进行全表扫描。而索引下推的优化就是将 Index Filter 的条件下推到引擎层,在使用 Index First Key 与 Index Last Key 进行筛选时,就带上 Index Filter 的条件再次筛选,以此来过滤掉不符合条件的记录对应的主键值,减少回表的次数,同时发给 Server 层的记录也会更少,全表扫描筛选的效率也会变高。
下面是未使用索引下推和使用索引下推的示意图:

下面是使用索引下推和使用索引下推的示意图:

3、总结

这里要注意的是如果在一开始没有用到索引,会依次将磁盘上的数据页读取到缓冲池中进行查询。
原文地址:https://www.cnblogs.com/mengxinJ/p/14045520.html#_label2
边栏推荐
猜你喜欢

(pytorch进阶之路二)word embedding 和 position embedding

数字人民币可以买理财产品了!建行APP在试点地区上线服务专区,实测体验如何?

How MySQL modifies a field to not null

Jenkins 通过检查代码提交自动触发编译

多年亿级流量下的高并发经验总结,都毫无保留地写在了这本书中

Promouvoir l'adaptation compatible et permettre le développement collaboratif du Service Express adaptatif gbase en mai

“软件定义世界,开源共筑未来” 2022开放原子全球开源峰会7月底即将开启

The 12 SQL optimization schemes summarized by professional "brick moving" old drivers are very practical!

Application of mongodb in Tencent retail premium code

【一起上水硕系列】Day Three - video
随机推荐
Mitsubishi manipulator demo program
vector的模拟实现
A simple understanding of hill ordering
Rosbag使用命令
DevSecOps: CI/CD 流水线安全的最佳实践
向量3(静态成员)
DDD understanding of Domain Driven Design
Quickly play ci/cd graphical choreography
How to open an account in flush? Is online account opening safe?
得物App数据模拟平台的探索和实践
Navicat Premium 连接Oracle 数据库(图文教程)
Ros2 pre basic tutorial | using cmakelists Txt compile ros2 node
MongoDB在腾讯零售优码中的应用
C# 实现插入排序
标准化、最值归一化、均值归一化应用场景的进阶思考
ORB_VI思想框架
Runmaide medical passed the hearing: Ping An capital was a shareholder with a loss of 630million during the year
希尔排序的简单理解
推荐几个AI智能平台
Promoting compatibility and adaptation, enabling coordinated development of gbase may adaptation Express