一条SQL查询语句是如果执行的

一条sql查询语句是如果执行的?

总体来说,MySQL大致分为server层和存储引擎层两大部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
explain SELECT * FROM T

### 执行过程
starting 0.0001660 10.573
Executing hook on transaction 0.0000140 0.892
starting 0.0000150 0.955
checking permissions 0.0000140 0.892
Opening tables 0.0002590 16.497
init 0.0000160 1.019
System lock 0.0000220 1.401
optimizing 0.0000140 0.892
statistics 0.0000200 1.274
preparing 0.0000200 1.274
Creating tmp table 0.0000540 3.439
executing 0.0004860 30.955
Sending data 0.0001190 7.580
end 0.0000140 0.892
query end 0.0000150 0.955
removing tmp table 0.0000160 1.019
query end 0.0000130 0.828
removing tmp table 0.0000150 0.955
query end 0.0000120 0.764
closing tables 0.0000130 0.828
freeing items 0.0001760 11.210
cleaning up 0.0000770 4.904

Server层

包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,例如:存储过程、触发器、视图等。

连接器

1.客户端与服务端建立连接,完成tcp三次握手之后,就执行ACL鉴权;
2.连接成功后,可通过:show processlist;来查看连接状态;
3.尽量使用长连接;
4.连接断开才会释放资源;
5.如果不断的建立连接,会占用太多的内存,导致OOM(内存溢出),会被系统强制kill掉,这种情况就是MySQL异常重启了;
6.上诉5的解决方案:1.定期断开连接,按需重连;2.MySQL5.7+版本,可通过:mysql_reset_connection来重新初始化连接资源,这个过程不需要重新ACL鉴权,而是会直接回到最初的连接状态。

查询缓存

1.k-v对的形式缓存,即是:查询语句+查询结果;
2.基本就是getOrSet的过程,找得到直接返回,找不到则执行查询,将执行结果缓存起来;
3.不能滥用SQL_CACHE,每次更新会清空建立的缓存,静态表推荐使用,频繁更新的不推荐使用,后者命中缓存的几率很低,基本都是走执行过程了。

分析器

举例子简单的sql语句:
select * from T where id = 1;
1.词法分析。MySQL会从输入的语句中的’select’这个关键字做识别,认为这是一条查询语句,继续会被T解析成表名T,id则会被识别为列ID;
2.语法分析。通过一系列的语法去检验sql语句是否满足MySQL的语法要求,如果语法错误则会出现SQL syntax error错误;

优化器

select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
1.决定使用哪个索引;
2.决定连接顺序,确认用哪种执行方案。例如:先查t1后t2,先t2后t1,这里方案是一致的,但是效率可能不同。
3.进入执行阶段;

执行器

分析器已经告诉你了需要查询还是更新,优化器也决定了使用哪种方案,然后就准备执行语句了。
1.判断是否有执行查询语句权限;
2.在工程上,如果命中了缓存,会在返回结果前做权限验证,查询也会在优化器前做precheck验证权限。
3.如果有权限,那么就开始打开表,执行器会根据表定义的engine引擎,使用这个引擎提供的查询接口。

存储引擎

主要是负责数据的存储以及提取咯。其架构是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎,mysql v-5.5.5版本,InnoDB开始成为了默认的引擎。
可以通过:engine=存储引擎 的方式来指定存储引擎。