【MySQL】数据库开发技术:内外连接与表的索引穿透深度解析

embedded/2025/3/1 11:00:08/

**前言:**本节内容主要讲解表的内连和外连以及索引的一部分。 注意: 索引是很重要的知识点。务必学习!!本节将会主要谈一谈什么是索引,如何理解索引。 以及怎么理解MySQL与磁盘的关系。 下面友友们开始学习吧!

ps:本节内容友友们只要想学习mysql都可以观看哦!!

目录

表的内连和外连接

内连接

外连接

左连接

右连接

索引

认识磁盘

MySQL与磁盘交互基本单位

建立共识

索引的理解


表的内连和外连接

内连接

内连接实际就是利用where子句对两种表形成的结果进行筛选。 连接是在from中。 以前学习的笛卡尔积实际上就是今天的内连接。 笛卡尔积和where判断,就叫做内连接。

下面来看一个内连接的案例:

找出SMITH的部门名称和部门编号

select ename, dname from emp inner join dept on emp.deptno = dept.deptno where ename = 'SMITH';

外连接

左连接

除了内连接, 就是外连接, 我们想让左侧的表, 完全显示。 右侧的表如果配不上, 就去掉。 左外连接的语法和内连接的语法一摸一样, 只不过是把left替换了inner。

现在做一下示例:

查询所有学生的成绩, 如果这个学生没有成绩, 也要将学生的个人信息显示出来:

create table stu(id int, name varchar(30));
insert into stu values(1, 'jack'), (2, 'kity'), (4, 'nono');
create table exam(id int, grade int);
insert into exam values(1, 56), (2, 76), (11, 8);

现在我们进行左连接查询。 我们上面的表中学生有三个。 同时成绩也有三个。 但是三个成绩的最后一个成绩的学号并不是上面三个学生里面的任何一个人。那么, 我们左连接查询:

select * from stu left join exam on stu.id = exam.id;

我们会发现, 即便我们的nono没有对应的成绩, 在第二张表中没有他, 他也被打印出来了。所以, 我们就能发现, 左连接就是,这个stu.id = exam.id的条件, 更偏向于stu表。

右连接

其实左连接和右连接是一样的。 所以, 我们就可以做这个案例:

对stu表和exam表进行联合查询, 把所有的成绩都显示出来, 即使这个成绩没有学生与它对应, 也要显示出来。

select * from stu right join exam on stu.id = exam.id;

其实和左连接差不多的。

以上就是内外链接的所有内容。 其实对于内连接来说, 就是判断条件时, 两张表是公平的。 对于左连接来说, 判断条件时, 偏向左表;对于右连接来说, 判断条件时, 偏向右表。

索引

索引是为了提高数据库的读取速度的。 我们所有的mysql的CURD操作都是在mysql的内存中进行, mysql在启动的时候会在内存中开辟一大块空间, 然后将数据库操作体现在内存里。 最后在合适的时候将数据刷新到外设。

我们首先要知道,MySQL的服务器, 本质是在内存中的, 所有的数据库的CURD操作, 全部都是在内存中进行的!——所以,索引也是如此。

我们还要知道, 提高算法效率的因素无非就是两个:

  • 1、组织数据的方式。
  • 2、算法本身。

所以, 这个索引一定是某种数据结构。

其实对于我们数据库里每一个表, 在系统下都对应的就是一个文件。文件都需要在磁盘上保存, 未来的数据在盘片上的一个一个小格子,也就是扇区当中。

认识磁盘

认识数据库, 我们就必须要认识一下磁盘。 数据库的数据其实本质上就是保存在磁盘上。 和磁盘文件如出一辙,同样是保存在磁盘上的一个一个小格子上面,即扇区。并且, 对于这一个一个的小格子, 其实就是512字节, 如今大都是4kb。具体的磁盘是什么样子的, 博主已经做过讲解, 下面是文章连接:linux基础IO——文件系统——学习硬件:磁盘_linux 逻辑盘 文件系统-CSDN博客

这里需要强调的是, 我们之前学习文件系统, 它的读取基本单位, 不是扇区,而是数据块。所以,系统读取磁盘, 是以块为单位的, 基本单位是4kb。

MySQL与磁盘交互基本单位

MySQL之下并不直接是硬件, 而是操作系统。

站在mysql的角度, 他认为与磁盘是以16kb进行交互, 但是mysql要经过OS, OS再与磁盘进行交互。 而OS与磁盘交互数据的大小为4kb。

所以, 在未来我们mysql要通过OS与磁盘交互, mysql一次就是操作16kb, 转化到OS和磁盘就是进行四次4kb的交互。 所以, 在mysql看来, 他不管, 他就是write, 操作系统就是必须在内部的文件缓冲区找到4个块, 然后四次交互将数据刷新到磁盘中。 同理, 未来mysql从磁盘中读数据, 就是要让OS读取四个快的数据,然后mysql读取数据read一次性读取16kb。 而对应的OS与磁盘之间就使用fsync系统调用进行交互。

mysql的这个16kb是mysql进行数据交互的基本单位, 这个基本单位就叫做page。

建立共识

首先, mysql中的数据文件, 是以page为单位保存在磁盘中的。

mysql的CURD操作, 都需要通过计算, 找到对应的插入位置, 或者找到对应要修改或者查询的的数据。

只要涉及到计算, 就必须有cpu参与, 而cpu参与, 就一定要让数据先移动到内存当中, 所以我们对应的磁盘当中的表当中的操作, 需要CURD操作的,就必须要先将表搬到OS内存中, 再从内存搬到mysql自己的缓冲区里面。 在自己的缓冲区里面用mysql自己的代码进行增删查改。而这个搬运过程里面搬运一次是4kb。

为了更好的搬运, 更好的提高搬运的速度。mysql服务器在内存中运行的时候,在服务器内部, 就申请了被称为Buffer Pool的大内存空间,来进行各种缓存。 其实就是很大的内存空间, 来和磁盘数据进行IO交互。 本质上就是减少系统和磁盘IO的消耗

索引的理解

我们向一个具有主键的表中, 乱序插入数据。为什么会发现这些数据会自动排序?这些是系统默认做的排序。 如果一个表中以整数为主键, 那么他就会按照主键的类型进行排序。

如何理解mysql中page的概念呢?mysql内部, 一定需要并且会存在大量的page, 也就决定了mysql必须将多个同时存在的page管理起来!要管理所有的mysql内的page, 需要先描述,再组织。

所以,不要简单的将page认为是一个内存块。 page内部也必须写入对应的管理信息!!!

struct page
{struct page* next;struct page* prev;char buffer[NUM];
}; 

16kb, new page, 将所有的page用’链表的形式管理起来 — 在buffer pool 内部, 对mysql中的page进行了一个建模。

现在回到为什么要自动排序?

根据我们理解就是用来优化查询效率。 page的数据结构是链表, 链表的特点也就是删除快, 查询修改慢。 所以优化查询的效率是必须的。 在查询某条数据记录的过程中, 我们一定是将整个页也就是16kb加载到内存当中。 所以就能IO次数。 page和page之间是链式, page之间也是链式。 但是链表查询太慢了, 为了提高效率——就从两个角度进行考虑:1、page之间和page之内。

所以就有了页目录。 我们知道, 对于一本书来说, 目录就是用来加速我们搜索书中信息的。而且, 目录也是占用纸张的。 所以, 目录就是一种空间换取时间的做法。 所以, 为什么我们musqld要对数据进行排序呢, 就是因为方便我们引入页目录, 因为只有数据的编号有序的, 我们的目录才能更快捷的查找找到对应的数据。 不仅仅是page内部的数据可以使用页目录, 如果page之间不适用页目录。 那么我们的page之间进行搜索的时间, 其实也是消耗大量时间的。所以,给我们的page之间也引入了页目录。

整个页目录如何创建, 就是再创建一批page, 这个page什么数据都不存, 只保存它管理的page指针。 这个指针指向他所管理的page的第一数据的起始位置。

可是如果我们的插入的数据非常多。 所以上级的页page也会非常多。 那么对于这些页目录page就也是要进行线序遍历。 所以,如果发生这种情况, 就要再从上层继续添加page。

所以, 往后我们查询数据就自顶向下查询数据。而这, 就是我们所说的B+树。 所以, mysql内的数据索引, 统一使用的是b+树索引的。 未来我们的b+树只有叶子节点用next与prev指针将他们连接起来。 其他的层并没有使用叶子节点进行连接起来。

这里有一些细节:就是叶子节点保存数据, 路上节点没有。 即非叶子节点不要数据, 只要目录。 为什么非叶子节点不存数据, 可以存储更多的目录项。 目录页可以更多的管理叶子page。 也就意味着这棵树一定是一个矮胖的树!——即途径路上节点减少, 找到目标数据只需要更少的page。 也就是IO的次数更少, 就在IO的层面提高了效率。而路上节点减少就意味 大大提高所以了搜索效率。所以就从两个层面上整体的提高了搜索的效率。

——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!


http://www.ppmy.cn/embedded/169035.html

相关文章

【北京迅为】iTOP-RK3568OpenHarmony系统南向驱动开发-第2章 内核HDF驱动框架架构

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

自动化测试无法启动(java.net.SocketException)

在运行测试代码,对浏览器进行自动化操作时,遇到了以下问题,添加依赖,编写了测试代码,但是程序无法运行 这个有两种原因(我使用的是谷歌浏览器): 网络问题: 因为需要从GitHub上下载对应包,所以有时候可能会出现网络问题,这个时候可以打开VPN之后,重新对程序进行启动 浏览器版本…

Linux系统软件管理

systemctl 控制软件启动和关闭 Linux系统很多软件支持使用systemctl命令控制:启动,停止,开启自启。 能被systemctl管理的软件,一般被称为:服务。 语法:systemctl start|stop|status|enable|disable 服务名…

FFmpeg av_read_frame 和iOS系统提供的 AVAudioRecorder 实现音频录制的区别

1. 第一种方式:使用 FFmpeg 的 av_read_frame 特点 底层实现:基于 FFmpeg,这是一个强大的多媒体处理库,直接操作音频流。灵活性:非常灵活,可以处理多种音频格式、编解码器和输入设备。复杂性:需要手动管理音频流、数据包(AVPacket)、内存释放等,代码复杂度较高。跨平…

ChatGPT Deep Research:重塑智能研究的未来边界

目录 **ChatGPT Deep Research:重塑智能研究的未来边界****核心功能与技术突破****技术架构与性能优势****部署计划与用户价值****未来展望与挑战****结语**ChatGPT Deep Research:重塑智能研究的未来边界 引言 在人工智能技术飞速迭代的今天,OpenAI推出的Deep Research功能…

C++11相较于C++98的新特性介绍:列表初始化,右值引用与移动语义

一,列表初始化 1.1C98中传统的{} C98中一般数组和结构体可以使用{}进行初始化: struct Date {int _year;int _month;int _day; };int main() {int a[] { 1,2,3,4,5 };Date _date { 2025,2,27 };return 0; } 1.2C11中的{} C11以后想统一初始化方式&…

Redis 深度解析

Redis 是一个开源的、内存中的数据结构存储系统,它支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合&#xff0…

【每日论文】Rank1: Test-Time Compute for Reranking in Information Retrieval

下载PDF或阅读论文,请点击:LlamaFactory - huggingface daily paper - 每日论文解读 | LlamaFactory | LlamaFactory 摘要 我们推出了Rank1,这是第一个旨在利用测试时计算能力的重排序模型。Rank1展示了在检索中利用推理语言模型&#xff08…