本文主要是介绍Select * from user的千层套路——一个sql是如何执行的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- Select * from user的千层套路
- MySql的基本架构
- 连接管理
- 解析与优化
- 查询缓存
- 语法解析和预处理
- 查询优化
- 执行器
- 存储引擎
- InnoDB
- MylSAM
- 最后
Select * from user的千层套路
作为一个java程序员,我们会经常和sql打交道,但是有事情我们确实不知道,比如sql语句背后的处理逻辑:
select * from user where id='1';
对于这么一条操作来说mysql服务器做了哪些处理呢?下面我们将说一下关于mysql数据库中对sql语句的处理逻辑
MySql的基本架构
要想要了解sql语句的内部处理逻辑,我们需要先学习Mysql的基本架构图,这样才能更好的把握Mysql数据库
从图中我们可以清楚的看到Mysql的架构和各个模块以及SQL语言的执行过程。
Mysql数据库整体可以分为Server层和存储引擎层两部分。其中Server层是共有的,而存储引擎层是可以以插件的形式进行扩展
一条Sql语句大概会经历链接管理、解析与优化、最后到存储引擎,这三个模块
连接管理
连接管理是SQL语句执行过程中的第一关,控制着客户端和Server服务端的交互,连接管理主要工作是客户端的身份认证和连接线程的管理、
每个客户端与Server建立连接时,服务器会创建一个线程来与客户端交互,交互的第一项内容就是验证客户端的身份,认证凭证是基于客户端发起连接请求时携带的主机信息、用户名、密码。
如果认证失败,则结束连接任务,并且返回Access denied for user的错误
如果认证成功,还会到权限表中查询该用户的权限,在此次连接下,后续的权限判断都是基于此时读取的权限为依据。
- 主要是负责客户端与服务端进行连接,当然在连接线程上,连接管理也做了优化,并不是每个客户端执行完任务之后,就把该线程销毁,连接管理会把这些线程缓存起来,等待新的连接,这也就不会频繁的创建和销毁线程,从而节约了开销。
解析与优化
完成连接管理之后,SQL 语句执行的第二步就是解析和优化,SQL 语句查询的所有操作都在这里了。
查询缓存
MySQL 服务器拿到查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。
但是实际使用中会有很多问题:
- 命中率低下:只要有稍微的不同就不会命中
- 缓存数据发送了变化,导致取到错误数据
- 一旦表中数据或结构改变了缓存也会删除
所以缓存对 MySQL 数据库来说弊大于利,所以在 MySQL 8.0 版本直接将查询缓存的整块功能删掉了
语法解析和预处理
如果查询缓存没有命中,接下来就需要进入正式的查询阶段了。因为客户端程序发送过来的请求只是一段文本而已,所以 MySQL 服务器程序首先要对这段文本做语法解析。
首先通过关键字将 SQL 语句进行解析,并且生成一个“解析树”。MySQL 解析器将使用 MySQL 语法规则验证和解析查询,例如,关键字是否使用正确、关键字的顺序是否正确或者引号是否前后匹配等。
预处理是根据一些 MySQL 规则进一步检查解析树是否合法,例如数据表和数据列是否存在,还会解析名字和别名,看看他们是否有歧义等。
查询优化
MySQL 的优化程序会对我们的语句做一些优化,如外连接转换为内连接、表达式简化、子查询转为连接等等。优化的结果就是生成一个执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的。
执行器
执行器会执行查询优化后的执行计划,通过与存储引擎交互,完成数据的查询操作,返回最终的数据结果。
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误
如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
比如我们这个例子中的表 user 中,假设 ID 字段没有索引,那么执行器的执行流程是这样的:
1、调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
2、调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
3、执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
到这里,执行 SQL 语句就执行完了,其实这内部还是非常复杂的。
存储引擎
到上面为止,SQL 语句就执行完了,但是与真实数据打交道的是存储引擎,存储引擎是 MySQL服务器对数据的存储和提取操作的封装模块。我们知道表是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎负责的事情。
为了实现不同的功能,MySQL提供了各式各样的存储引擎,不同存储引擎管理的表具体的存储结构可能不同,采用的存取算法也可能不同。比如,MySQL5.7 之后默认的 InnoDB 存储引擎。
InnoDB
InnoDB是一个事务型的存储引擎,有行级锁定和外键约束,提供了具有提交、回滚和崩溃回复的事务安全,但是对比MyLSAM引擎,写的效率会差一些,并且会占用更多的磁盘空间以保持数据和索引
特点:
- 更新多的表,适合处理多重并发的更新请求
- 支持事务
- 可以从灾难中恢复(从bin-log日志等)
- 外键约束,支持外键
- 支持自动增加列属性auto_increment
MylSAM
MylSAM存储引擎独立于操作系统,系统兼容性好。在建表的时候会创建三个文件,分别是.fm,.MYD,.MYI。这样会导致对大文件的操作慢,但是由于.MYD单独存放数据自然可以优化数据库的查询等操作
.fm:存储表的定义,即表结构
.MYD:存储表里面的数据
.MYI:存储所以
特点:
- 不支持事务
- 不支持外键
- 查询速度快,但是如果数据库表insert和update操作多的话由于采用表锁导致效率低
- 对表进行加锁
最后
- 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
- 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
- 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。
这篇关于Select * from user的千层套路——一个sql是如何执行的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!