视频地址 https://www.bilibili.com/video/bv1Sq4y1377k
从我们学习Java开始,我们就学了很多种操作数据库的方式,最开始的JDBC、后面的JPA、HIbernate、MyBatis,那你是否想过,我们只是简单的写了一个sql,最终是如何到达数据库、返回结果?这中间都经历了什么呢?
不管我们是用原生的JDBC还是后面的ORM框架,我们都会引入这样一个pom文件,这就是MySQL驱动,我们通过这个驱动去连接MySQL
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
那么看起来就像这样
我们知道,每一个系统都是有并发量的,为了保证系统高效的运行,就注定了不可能是单线程的运行,同样操作数据的时候也是一样,我们学过了很多数据库连接池,C3P0、DBCP、Druid等,这些是在Java这边的连接池,同理数据库层面肯定也不能只是一个线程来执行我们的任务,所以数据库这边也会有对应的连接池。
当然上面是省略了一部分,那就是数据库对你这个连接进行身份校验的操作。
现在想一想,当一个请求到了数据库,数据库收到之后是不是就得分配一个线程,然后去执行这个sql呢?
其实这当然不是了,毕竟数据库是一个系统,它不是人,当我们要去电脑里面找寻某个文件的时候,我们脑海里是知道这个文件在什么的位置的,它叫什么。
同样的系统要把我们的这个请求进行解析,解析成它可以理解的语法,然后再去做相关操作,具体的逻辑顺序如下:
SQL接口
这个sql接口,就是用来接受应用服务器发送的sql
当应用服务器通过连接通道发送sql到数据库后,数据库从连接池里面拿到后,分发一个线程去进行处理,第一步就是把sql交给这个sql接口。
SQL解析器
某种程度上讲,系统和我们人类是类似的,我们的眼睛如同SQL接口获取信息,SQL解析器则如同我们的大脑,对获取的内容进行解析、拆分,然后变成数据库所能理解的内容。
查询优化器
一个简单的sql SELECT name FROM user WHERE id = 1
它可能有多种执行策略:
- 先查询出全部的 name,然后再取出 id=1 的数据
- 直接先找寻id=1 的数据,然后再取出它的 name
毫无疑问肯定是第二种策略更好,第一种就是全表扫描了,当然真正的执行策略并不一定就是我这里所说的这样,这只是一个比喻。
一个稍微复杂一点的SQL,它很有可能会有很多种的执行策略,那么这个查询优化器,就会帮助我们来选择一个最合适的策略。
执行器
当优化器选择最合适的执行策略之后,就由执行器去调用对应的引擎去操作硬盘上的数据了。(虽然引擎有很多比如innodb、myisam等,但用的最多的还是innodb了)
buffer pool
在InnoDB引擎下,所有的操作都是先把数据读取到缓冲池
(这个就是内存的一块区域),然后在这个区域内进行增删改查操作,之所以这样做是因为在内存操作的性能要远远高于在硬盘中的操作。
理解了上面都执行流程之后,我们只需要记住这个执行链,然后再基于自己的理解就好了
- SQL接口 > SQL解析器 > 查询优化器 > 执行器 > 调用引擎接口去执行