一、一条sql查询语句是如何执行的
比如我们查询的SQL语句为:select * from T where id = 1;
其内部执行的过程可由下图介绍:
1、mysql架构介绍
MySQL 分为 Server层 和 存储引擎层
server层::包括连接器、查询缓存、分析器、优化器、执行器等,涵盖mysql大多数核心服务功能,以及所有的内置函数(如日期,时间,数学等),所有跨存储引擎的功能都在此实现,如:存储过程、触发器、视图。
**存储引擎层:**负责数据的存储和提取,支持 InnoDB、MyISAM、Memory等多个存储引擎。mysql 5.5版本后默认的是 InnoDB。
2、连接器
通过连接器连接到相应的数据库,连接器负责跟客户端建立连接、获取权限、维持和管理连接。
命令一般这样写:
MySQL -h$ ip -p$port -u$user - p
命令中 mysql 是客户端工具,用于和服务器建立连接。在完成三次握手后,连接器开始通过用户名密码进行认证,认证通过后,连接器会获取拥有的权限,此后至连接中断前,都依赖此时读到的权限。
这意味着,用户建立连接后,即便超管改掉了你的权限,但是对于你此时是不生效的,只要新建的连接才会使用新的权限
连接完成后,无动作默认 8小时 断开连接,断开连接后,需要重连才可操作。
长连接: 客户端的多个请求使用的是一个连接
短链接: 客户端的请求完成即断开连接,再次请求再连接,完成后断开。
建议多使用长连接
全部使用长连接。会发现,Mysql占用的内存过大,因为mysql执行使用的内存在连接对象中,断开连接才会释放。所有长连接累积下来,会造成内存占用太大,被系统强行kill ,现象看就是 mysql异常重启了
解决1、长连接累积下来,导致占用内存过大被系统Kill。
- 定期断开长连接。
- mysql 5.7版本后,每次执行打的操作后, 执行 mysql_reset_connection进行初始化连接,不会重连和重新权限认证,将连接恢复到刚创建的状态。
2、查询缓存:
建立连接后,就开始执行 select 语句,第二步就是查询缓存
mysql 将第一次执行的sql语句和结果以 key-value的形式保存到缓存中(更新操作会清空缓存),下次执行相同的语句会先到缓存中查询 key 存在就直接将 value返回,如果不存在就会继续执行 再将结果 key-value保存在缓存中。
大多情况下不建议使用查询缓存
对于更新频繁的表,这个表的所有查询缓存会被频繁的情空,会导致,缓存还没用过,就没清空了,导致 查询缓存的命中率低。除非有一张静态表,长时间才更新一次,可以使用查询缓存。
mysql 8.0版本完全去除了查询缓存的模块
解决2、按需使用查询缓存
- 配置默认不使用缓存:query_cache_type=DEMAND
- 显示指定使用缓存的SQL_CACHE:select SQL_CHACHE * from t
3、分析器
如果没有命中缓存,接下来就到了真正执行语句了。
分析器需要先进行词法分析,比如识别 select 知道这是个查询语句,T是表名,id是列名。
此法分析完成后,就要进行语法分析,判断是否符合 sql 语法规范。
4、优化器
经过分析器,mysql知道你要做什么,在开始执行之前,会进行优化器的处理。
优化器在表中又对各索引的适合,决定使用哪个索引,活一个语句又多个关联表,他决定各个表的连接顺序,确定执行方案
5、执行器
分析器知道你要干什么,优化器知道该怎么做,下面进行执行阶段
开始执行之前,先判断是否又有该表的权限,有权限继续执行。
比如:select * from T where ID = 10
表T中 Id字段没有索引,执行器执行流程是这样的:
- 调用 InnoDB存储引擎接口,获取这个表的第一行,判断Id 是否等于 10 ,不满足则取下一行,直至取到最后一行。执行器将满足条件的数据作为结果集返回到客户端。
对于有索引的表,第一次调用:满足条件的第一行后,循环调用:满足条件的下一行。