为了执行SQL语句,MySQL的架构是怎样设计的

1. 把MySQL当个黑盒子一样执行SQL语句

上一讲我们已经说到,我们的系统采用数据库连接池的方式去并发访问数据库,然后数据库自己其实也会维护一个连 接池,其中管理了各种系统跟这台数据库服务器建立的所有连接

我们先看下图回顾一下

当我们的系统只要能从数据库连接池获取到一个数据库连接之后,我们就可以执行增删改查的SQL 语句了

从上图其实我们就可以看到,我们可以通过数据库连接把要执行的SQL语句发送给MVSQL数据库

然后呢?大部分同学了解到这个程度就停下来了,然后大家觉得要关注的可能主要就是数据库里的表结构,建了哪些索引,然后就按照SQL语法去编写增删改查SQL语句,把MVSQL当个黑盒子去执行SQL语句就可以了。

我们只知道执行了inset语句之后,在表里会多出来一条数据;执行了update语句之后,会对表里的数据进行更改;执 行了delete语句之后,会把表里的一条数据删除掉;执行了select语句之后,会从表里查询一些数据出来

如果语句性能有点差?没关系,在表里建几个索引就可以了!可能这就是目前行业内很多工程师对数据库的一个认知,完全当他是个黑盒子,来建表以及执行SQL语句。

但是大家既然跟着我开始学习了,从现在开始就要打破这种把数据库当黑盒子的认知程度,要深入底层,去探索数据 库的工作原理以及生产问题的优化手段!

2. 一个不变的原则:

现在假设我们的数据库服务器的连接池中的某个连接接收到了网络请求,假设就是一条SQL 语句,那么大家先思考一 个问题,谁负责从这个连接中去监听网络请求?谁负责从网络连接里把请求数据读取出来?

我想很多人恐怕都没思考过这个问题,但是如果大家对计算机基础知识有一个简单了解的话,应该或多或少知道-点,那就是网络连接必须得分配给一个线程去进行处理,由一个线程来监听请求以及读取请求数据,比如从网络连接 中读取和解析出来一条我们的系统发送过去的SQL语句,如下图所示:

3. 接口负责处理接收到的SQL语句

接着我们来思考一下,当MySQL内部的工作线程从一个网络连接中读取出来一个SQL语句之后,此时会如何来执行这个SQL语句呢?

其实SQL是一项伟大的发明,他发明了简单易用的数据读写的语法和模型,哪怕是个产品经理,或者是运营专员,甚 至是销售专员,即使他不会技术,他也能轻松学会使用SQL语句。

但如果你要去执行这个SQL语句,去完成底层数据的增删改查,那这就是一项极度复杂的任务了!

所以MySQL内部首先提供了一个组件,就是SQL接口(SQL Interface),他是一套执行SQL语句的接口,专门用于执行我们发送给MySQL的那些增删改查的SQL语句

因此MySQL的工作线程接收到SQL语句之后,就会转交给SQL接口去执行,

如下图

4. 查询解析器:让MySQL语句进行解析

接着下一个问题来了,SQL 接口怎么执行SQL语句呢?你直接把SQL语句交给MySQL,他能看懂和理解这些SQL语句吗?

比如我们来举一个例子,现在我们有这么一个SQL语句:

select id,name,age from users where id=1

这个SQL语句,我们用人脑是直接就可以处理一下,只要懂SQL语法的人,立马大家就知道他是什么意思,但是MVSQL自己本身也是一个系统,是一个数据库管理系统,他没法直接理解这些SQL语句!

所以此时有一个关键的组件要出场了,那就是查询解析器

这个查询解析器 (Parser) 就是负责对SQL语句进行解析的,比如对上面那个SQL语句进行一下拆解,拆解成以下几个部分:

1.我们现在要从“users”表裏查询数据

2.查询”id”字段的值等于1的那行数据

3.对查出来的那行数据要提取里面的“id,name,age”叁个字段

所谓的SQL解析,就是按照既定的SQL语法,对我们按照SQL语法规则编写的SQL语句进行解析,然后理解这个SQL语句要干什么事情,如下图所示:

5. 查询优化器:选择最优的查询路径

当我们通过解析器理解了SQL语句要干什么之后,接着会找査询优化器(0ptimizer)来选择一个最优的查询路径。

可能有同学这里就不太理解什么是最优的查询路径了,这个看起来确实很抽象,当然,这个查询优化器的工作原理,后续将会是我们分析的重点,大家现在不用去纠结他的原理。

但是我们可以用一个极为通俗简單的例子,让大家理解一下所謂的最优查询路径是什么。

就用我们刚才講的那个例子好了,我们现在理解了一个SQL想要干这么一个事儿:我們现在要從users ”表里查询数 据,查询id”字段的值等于1的那行数据,對查出来的那行数據要提取里面的”id,name,age”三个字段。

事是明白了,但是到底应该怎么来实现呢?

你看,要完成這个事儿我们有以下幾個查询路径(纯属用于大家理解的例子,不代表真实的MVSQL原理,但是通过这个例子,大家肯定能理解所谓最优查詢路径的意思):

1.直接定位到'users”表中的id”字段等于1的一行数据,然后查出来那行数据的id,name,age”三个字段的值就可以了

2.先把'users”表中的每一行数据的id,name,age”叁个字段的值都查出来,然后从这批数据裏过滤出来id字段等于1的那行数据的id,name,age”三个字段

上面这就是一个最简单的SQL语句的两種实现路径,其实我们会发现,要完成这个SQL语句的目标,兩个路径都可以做到,但是哪一种更好呢?显然感觉上是第一种查询路径更好一些。

所以查询优化器大概就是干这个的,他会針对你编写的幾十行、幾百行甚至上千行的复雜SQL语句生成查询路径树,

然后从里面选择一条最优的查询路径出来

相当于他会告诉你,你应该按照一个什么样的步骡和顺序,去执行哪些操作,然后一步一步的把SQL语句就合完

我们来一起看看下面的图:

6. 调用存储引擎接口,真正执行SQL语句

最后一步,就是把查询优化器选择的最优查询路径,也就是你到底应该按照一个什么样的顺序和步去执行这个SOL语句的计划,把这个计划交给底层的存儲引警去真正的执行。这个存储引擎是MVSOL的架构设計中很有特色的一个环节。

不知道大家是否思考过,真正在执行SQL语句的时候,要不然是更新数据,要不然是查询数据,那么数据你觉得存放在哪里?

说白了,数据库也不是什么神秘莫测的东西,你可以把他理解为本身就是一个类似你平时写的图书馆管理系统电信计费系统、电商订单系统之类的系统罢了,

数据库自己就是一个编程语言写出来的系统而已,然后启动之后也是一个进程,执行他里面的各种代码,也就是我们 上面所说的那些东西。所以对数据库而言,我们的数据要不然是放在内存里,要不然是放在磁盘文件里,没什么特殊的地方!

所以我们来思考一下,假设我们的数据有的存放在内存里,有的存放在磁盘文件里,如下图所示,

那么现在问题来了,我们已经知道一个SQL语句要如何执行了,但是我们现在怎么知道哪些数据在内存里?哪些数据 在磁盘里?我们执行的时候是更新内存的数据?还是更新磁盘的数据?我们如果更新磁盘的数据,是先查询哪个磁盘 文件,再更新哪个磁盘文件?

是不是感觉一头雾水

所以这个时候就需要存储引擎了,存储引擎其实就是执行SQL语句的,他会按照一定的步骤去查询内存缓存数据,更 新磁盘数据,查询磁盘数据、等等,执行诸如此类的一系列的操作,如下图所示。

MySQL的架构设计中,SQL接口、SQL解析器、查询优化器其实都是通用的,他就是一套组件而已

但是存储引擎的话,他是支持各种各样的存储引擎的,比如我们常见的InnoDB、MYISAM、Memory等等,我们是可以 选择使用哪种存储引擎来负责具体的SQL语句执行的。

当然现在MVSOL一般都是使用InnoDB存储引擎的,至干存储引警的原理,后续我们也会深入一步一步分析,大家不必 着急。

7. 执行器:根据执行计划调用存储引擎的接口

那么看完存储引擎之后,我们回过头来思考一个问题,存储引引擎可以帮助我们去访问内存以及磁盘上的数据那么是谁来调用存储引擎的接口呢?

其实我们现在还漏了一个执行器的概念,这个执行器会根据优化器选择的执行方案,去调用存储引擎的接口按照一定的顺序和步骤,就把SQL语句的逻辑给执行了。

举个例子,比如执行器可能会先调用存储引擎的一个接口,去获取users”表中的第一行数据,然后判断一下这个数据 的“id”字段的值是否等于我们期望的一个值,如果不是的话,那就继续调用存储引擎的接口,去获取“users”表的下一行数据。

就是基于上述的思路,执行器就会去根据我们的优化器生成的一套执行计划,然后不停的调用存储引擎的各种接口去完成SQL语句的执行计划,大致就是不停的更新或者提取一些数据出来

我们看下图的示意

8. 小思考题:打开脑洞,你觉得不同的存储引擎是用来干什么的?

今天给大家留一个小的思考题,就是你先别管MySQL有哪些存储引擎,你就从业务场景来出发考虑,有的场景可能是 高并发的更新,有的场景可能是大规模数据查询,有的场景可能是允许丢失数据的

那么你觉得如果让你来设计存储引擎,你觉得应该有哪些存储引擎,分别适用于什么场景?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818573.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化-ECharts Html项目实战(12)

在之前的文章中,我们深入学习ECharts特殊图表中的矩形树图以及Echarts中高级功能的多图表联动。想了解的朋友可以查看这篇文章。同时,希望我的文章能帮助到你,如果觉得我的文章写的不错,请留下你宝贵的点赞,谢谢。 数…

Directory Monitor:全方位监控文件系统变动的专业利器

目录 一、软件介绍 二、软件功能 三、软件特点 四、安装说明 五、使用说明 一、软件介绍 Directory Monitor是一款强大易用的实时文件系统监视工具,它由Michael Humpa开发,专为满足用户监控特定目录下文件和子目录变化的需求。无论是为了保障系统安…

C++中调用QML函数

在.qml中写一个函数 import QtQuick import QtQuick.Controls import MyObj 1.0Window {id: windowobjectName: "window"width: 480height: 480visible: truetitle: qsTr("Hello World")//目标函数function qmlFunc(i, s) {return "success"}Bu…

python与设计模式之工厂模式的那些事儿

一、工厂模式 工厂模式实现了按需创建的最佳模式,其目的是为了隐藏创建类的细节与过程,通过一个统一的接口来创建所需的对象。 话说没了皇位争夺权的皇三接到了一个外征的工作,始皇给了5个亿的经费让皇三组建一个军队。打权总是要进行武器采…

探索Python编程:5个实用技能示例及代码解析

Python作为一种流行且多功能的编程语言,被广泛应用于各种领域。本文将介绍Python编程中的五个实用技能 1. Web 开发 在Web开发中,我们可以使用Flask框架来快速构建Web应用程序。下面的代码示例展示了一个简单的Flask应用,当用户访问根路径时…

【Java开发指南 | 第二篇】标识符、Java关键字及注释

读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 标识符Java关键字Java注释 标识符 Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($&#xff0…

pyqt5使用matplotlib绘图

说明 在pyqt5中使用matplotlib步骤: 1、引入plt 2、引入FigureCanvas 3、生成figure 4、取得FigureCanvas 5、将FigureCanvas加入容器中 6、调用plt函数来绘图 代码 import sys # 1、引入plt import matplotlib.pyplot as plt import numpy as np # 2、引入Figur…

为什么阿里巴巴不让使用JDK自带的线程池?

阿里巴巴在《阿里巴巴Java开发手册》中建议开发者不要直接使用 java.util.concurrent.Executors 类中的静态工厂方法来创建线程池,而是推荐直接使用 ThreadPoolExecutor 类来实例化线程池,主要原因如下: 资源耗尽的风险: JDK内置的…

CentOS 7安装、卸载MySQL数据库

说明:本文介绍如何在CentOS 7操作系统下使用yum方式安装MySQL数据库,及卸载; 安装 Step1:卸载mariadb 敲下面的命令,查看系统mariadb软件包 rpm -qa|grep mariadb跳出mariadb软件包信息后,敲下面的命令…

【Qt】:事件的处理

系统相关 一.鼠标事件二.键盘事件三.定时器 事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在个同的的刻友出的。当用广投下鼠标、敲下键盘,或者是窗口需要…

【C++】每日一题 48 旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 #include <vector> using namespace std;class Solution { public:void …

第四百六十二回

文章目录 1. 概念介绍2. 实现方法3. 示例代码4. 内容总结 我们在上一章回中介绍了"关于MediaQuery的优化"相关的内容&#xff0c;本章回中将介绍readMore这个三方包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的readMore是一个…

【团体程序设计天梯赛 往年关键真题 25分题合集 详细分析完整AC代码】(L2-001 - L2-024)搞懂了赛场上拿下就稳了

L2-001 紧急救援 最短路路径打印 样例 输入1 4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2输出1 2 60 0 1 3分析 用一遍dijkstra算法。设立 n u m [ i ] num[i] num[i]和 w [ i ] w[i] w[i]表示从出发点到i结点拥有的路的条数&#xff0c;以及能够找到的救援队的数目…

Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)

什么是 WebSocket 客户端 A 和客户端 B 的消息传播需要借助服务器的中转 (原因是内网不能给另一个局域网的内网直接联通, 需要借助服务器的外网做 “中介”) (NAT 地址转换) Http 协议 不支持实时通讯 (或者说不支持服务器主动推送数据给客户端) TCP 本身是具有服务器推送数据这…

【verilog】 reg与寄存器的关系

一、前言 在Verilog中经常用reg定义具有数据寄存功能的单元&#xff0c;但在verilog的使用中&#xff0c;并不代表其一定就是寄存单元&#xff0c;reg还能进行组合逻辑描述&#xff0c;并且在一些场景下&#xff0c;只能使用reg来申明变量。 二、reg型变量生成组合逻辑 在Ve…

Java 中文官方教程 2022 版(四十四)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html 调用方法 原文&#xff1a;docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html 反射提供了一种在类上调用方法的方式。通常&#xff0c;只有在非反射代码中无法将类的实例强制转换为…

linux shell脚本编写(2)

Shell: 命令转换器&#xff0c;高级语言转换成二进制语言。是Linux的一个外壳&#xff0c;它包在Lniux内核的外面&#xff0c;用户和内核之间的交互提供了一个接口。 内置命令&#xff1a;在shell内部不需要shell编辑 外置命令&#xff1a;高级语言要用shell转换成二进制语言 …

分析Quartz(v2.3.2)QuartzSchedulerThread.run核心方法

文章目录 前言一、QuartzSchedulerThread.run 前言 最近项目中的定时任务&#xff0c;用Quartz框架取代了。最近也在学习Quartz框架这方面的知识&#xff0c;但是看代码过程有很多难以理解的地方。项目中使用数据库来存储的任务&#xff0c;本篇文章就从QuartzSchedulerThread…

(一)Jetpack Compose 从入门到会写

基本概念 Compose 名称由来 众所周知&#xff0c;继承在功能拓展上表现的很脆弱&#xff0c;容易类、函数爆炸&#xff0c;通过代理和包装进行组合会更健壮。 Compose 意为组合&#xff0c;使用上也是把 Compose 函数以 模拟函数调用层级关系的方式 组合到一起&#xff0c;最终…

PCL中VTK场景添加坐标系轴显示

引言 世上本没有坐标系&#xff0c;用的人多了&#xff0c;便定义了坐标系统用来定位。地理坐标系统用于定位地球上的位置&#xff0c;PCL点云库可视化窗口中的坐标系统用于定位其三维世界中的位置。本人刚开始接触学习PCL点云库&#xff0c;计算机图形学基础为零&#xff0c;…