[MySQL#10] 索引底层(1) | Page | 页目录

 目录

1. 初识索引

2. 认识磁盘

3. MySQL与磁盘交互基本单位

4. 索引的理解

1. 重谈Page

2. 为什么IO交互要用Page

3. 有主键的表插入数据时的排序

4. 单个Page与多个Page

4.1 单个Page

4.2 多个Page

目录

单Page目录

多Page目录


在看本文之前,可以回顾一下这两篇前文~

[MySQL#5] 表约束(2) | 唯一键 | 外键 | 简易商店数据库

【Linux】(26) 详解磁盘与文件系统:从物理结构到inode机制

1. 初识索引

  • 索引是提高数据库性能的关键工具。
  • 它通过改变数据的组织方式,显著提升查询速度,而无需增加硬件资源或修改应用程序代码。
  • 然而,索引的使用也并非没有代价。
  • 查询速度的提升是以插入、更新和删除操作的性能下降为代价的,因为这些写操作会增加大量的I/O操作。
  • 因此,索引的价值在于提高海量数据的检索速度。

MySQL的CURD操作与内存

  • 所有MySQL的CURD操作都在内存中进行。MySQL在启动时会预先开辟一大块内存空间,用于缓存数据。
  • 这些数据会在适当的时候被刷新到磁盘中进行持久化
  • 因此,MySQL服务器本质上是在内存中运行的,所有的数据库操作都在内存中进行。索引同样也是在内存中的一种特定结构
  • 索引是提高效率的,一般我们知道提高算法效率的因素:1. 组织数据的方式 ,2. 算法本身
  • 索引是更改特定组织数据的方式,把以前数据的组织方式以新的数据结构组织起来。所以索引是内存中一种特定组织的一种数据结构,具体是什么结构后面再说,

索引的类型

常见的索引类型包括:

  • 主键索引(Primary Key)
  • 唯一索引(Unique)
  • 普通索引(Index)
  • 全文索引(Fulltext)——主要用于解决中文索引问题

创建海量数据表

为了演示索引的效果,我们先创建一个包含800万条记录的表,并观察没有索引时的查询性能。

-- 产生随机字符串
delimiter $$
create function rand_string(n INT)
returns varchar(255)
begindeclare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';declare return_str varchar(255) default '';declare i int default 0;while i < n doset return_str = concat(return_str, substring(chars_str, floor(1 + rand() * 52), 1));set i = i + 1;end while;return return_str;
end $$
delimiter ;-- 产生随机数字
delimiter $$
create function rand_num()
returns int(5)
begindeclare i int default 0;set i = floor(10 + rand() * 500);return i;
end $$
delimiter ;-- 创建存储过程,向雇员表添加海量数据
delimiter $$
create procedure insert_emp(in start int(10), in max_num int(10))
begindeclare i int default 0;set autocommit = 0;repeatset i = i + 1;insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)values (start + i, rand_string(6), 'SALESMAN', 0001, curdate(), 2000, 400, rand_num());until i = max_numend repeat;commit;
end $$
delimiter ;-- 执行存储过程,添加8000000条记录
call insert_emp(100001, 8000000);

注意:创建表单前要注意,恢复默认结束符:使用 delimiter ; 将结束符恢复为默认的分号 ;

查询性能测试

查询员工编号为998877的员工:

select * from EMP where empno = 998877;

没有索引时,查询非常慢,耗时约4.29秒。在实际项目中,如果放在公网中,同时有1000人并发查询,可能会导致系统崩溃。

解决方法:创建索引

alter table EMP add index(empno);

创建索引后,查询速度大幅提升。


2. 认识磁盘

硬件理解

MySQL 给用户提供存储服务,而存储的都是数据,数据在磁盘这个外设当中。

磁盘是计算机中的一个机械设备,相比于计算机其他电子元件,磁盘效率是比较低的,在加上IO本身的特征,可以知道,如何提升效率,是 MySQL 的一个重要话题。

磁盘结构

  • 扇区:数据库文件保存在磁盘的扇区中。每个扇区通常是512字节。
  • 柱面(Cylinder):同半径的磁道构成一个柱面。
  • 磁头(Heads):每个盘面有一个磁头,磁头和盘面的对应关系是1对1的。
  • CHS(Cylinder, Head, Sector):通过磁头、柱面和扇区编号定位扇区。
  • LBA(Logical Block Addressing):系统使用线性地址,最终转换为CHS。

再细看磁盘中一个盘片

扇区

数据库文件,本质其实就是保存在磁盘的盘片当中。也就是上面的一个个小格中,就是我们经常所说的扇区。当然,数据库文件很大,也很多,一定需要占据多个扇区。

题外话:

  • 从上图可以看出来,在半径方向上,距离圆心越近,扇区越小,距离圆心越远,扇区越大
  • 那么,所有扇区都是默认512字节吗?目前是的,我们也这样认为。因为保证一个扇区多大,是由比特位密度决定的。
  • 不过最新的磁盘技术,已经慢慢的让扇区大小不同了,不过我们现在暂时不考虑。
  • 我们在使用Linux,所看到的大部分目录或者文件,其实就是保存在硬盘当中的。(当然,有一些内存文件系统,如: proc , sys 之类,我们不考虑)
  • 建立数据库其实就是在linux下建立一个目录,建立一张表其就是在linux建立一个文件。

所以,最基本的,找到一个文件的全部,本质,就是在磁盘找到所有保存文件的扇区。

而我们能够定位任何一个扇区,那么便能找到所有扇区,因为查找方式是一样的。

定位扇区

  • 柱面(磁道): 多盘磁盘,每盘都是双面,大小完全相等。那么同半径的磁道,整体上便构成了一个柱面
  • 每个盘面都有一个磁头,那么磁头和盘面的对应关系便是1对1的
  • 所以,我们只需要知道,磁头(Heads)、柱面(Cylinder)(等价于磁道)、扇区(Sector)对应的编号。即可在磁盘上定位所要访问的扇区。这种磁盘数据定位方式叫做 CHS 。
  • 不过实际系统软件使用的并不是 CHS (但是硬件是),而是 LBA ,一种线性地址,可以想象成虚拟地址与物理地址。系统将 LBA 地址最后会转化成为 CHS ,交给磁盘去进行数据读取。不过,我们现在不关心转化细节,知道这个东西,让我们逻辑自洽起来即可。

结论

我们现在已经能够在硬件层面定位,任何一个基本数据块了(扇区)。那么在系统软件上,就直接按照扇区进行IO交互吗?不是

  • 如果操作系统直接使用硬件提供的数据大小进行交互,那么系统的IO代码,就和硬件强相关,换言之,如果硬件发生变化,系统必须跟着变化
  • 从目前来看,单次IO 512字节,还是太小了。IO单位小,意味着读取同样的数据内容,需要进行多次磁盘访问,会带来效率的降低。
  • 之前学习文件系统,就是在磁盘的基本结构下建立的,文件系统读取基本单位,就不是扇区,而是数据块。

故,系统读取磁盘,是以块为单位的,基本单位是 4KB 。

磁盘访问方式

  • 随机访问(Random Access):扇区地址不连续,磁头需要移动。
  • 连续访问(Sequential Access):扇区地址连续,磁头移动较少,效率较高。

3. MySQL与磁盘交互基本单位

软件理解

MySQL是一个应用层软件,依赖操作系统进行I/O操作。操作系统和磁盘之间的I/O单位是4KB,而MySQL为了提高效率,以16KB为单位先和 OS 进行I/O操作。

Buffer Pool

MySQL在内存中申请了一个大内存空间(Buffer Pool),用于缓存数据。默认大小为128MB。Buffer Pool用于减少磁盘I/O次数,提高查询性能。

I/O流程

  1. MySQL向操作系统请求16KB数据。
  2. 操作系统从磁盘读取4个4KB的数据块,加载到文件缓存区。
  3. 数据从文件缓存区加载到MySQL的Buffer Pool。
  4. MySQL在Buffer Pool中对数据进行处理。
  5. 更新数据时,MySQL将数据写入Buffer Pool,然后通过操作系统刷新到磁盘。

验证

  • 16*1024=16384
  • 磁盘这个硬件设备的基本单位是 512 字节,而 MySQL InnoDB引擎 使用 16KB 进行IO交互。
  • 即, MySQL 和磁盘进行数据交互的基本单位是 16KB 。
  • 这个 16KB 的基本数据单元,在 MySQL 这里叫做 page(注意和系统的page区分),它们是1:4的关系

共识要点

  1. MySQL以16KB page为单位进行I/O
  2. MySQL有Buffer Pool,数据先加载到Buffer Pool,再进行处理。
  3. 减少系统和磁盘I/O次数,一次I/O的数据量越大,效率越高。

以上就是我们学习索引的预备工作,下面正式开始学习索引~

4. 索引的理解

建立测试表

create table if not exists user (id int primary key,age int not null,name varchar(16) not null
) engine=InnoDB;

插入多条记录

insert into user (id, age, name) values (3, 25, 'Alice');
insert into user (id, age, name) values (1, 20, 'Bob');
insert into user (id, age, name) values (2, 22, 'Charlie');

查看插入结果

发现数据是有序的,这是因为MySQL会默认按照主键进行排序。

我们向一个具有主键的表中,乱序插入数据,发现数据会自动排序。谁做的?为什么这么做?

为了解决这个问题,我们需要重新探讨一下MySQL中的Page概念。

1. 重谈Page

数据读取流程

  • 磁盘上的文件数据:首先会被读到操作系统的文件缓存区中。
  • MySQL的Buffer PoolMySQL在启动时会为自己申请一个Buffer Pool,用于缓存数据。MySQL与操作系统之间进行I/O交互的基本单位是16KB,这是为了提高效率,减少I/O成本。

Page的概念

  • Page:MySQL的基本数据单位,大小为16KB。
  • Buffer Pool:可以加载多个Page,使用双向链表连接。

管理Page的方法

  • 先描述,再组织不要简单地将Page认为是一个内存块,Page内部也必须写入对应的管理信息。
  • 链表管理:所谓在MySQL中申请一个Page,实际上是new一个Page对象。然后将所有Page用“链表”的形式管理起来。我们在Buffer Pool内部对MySQL中的Page进行了建模。

2. 为什么IO交互要用Page

Page的重要性

  • 问题: MySQL和磁盘进行I/O交互时,采用Page方案的原因是为了提高效率。如果每次只加载需要的数据,例如查找id=2的记录,第一次加载id=1,第二次加载id=2,一次一条记录,那么就需要2次I/O。如果要找id=5,那么就需要5次I/O。
  • 批量加载:但如果这5条记录(或更多)都被保存在一个Page中(16KB,能保存很多记录),那么第一次I/O查找id=2时,整个Page会被加载到MySQL的Buffer Pool中完成一次I/O。此后如果查找id=1,3,4,5等,完全不需要进行I/O,而是在内存中进行。因此,在单Page内大大减少了I/O的次数。

局部性原理

  • 不能严格保证:我们不能严格保证用户下次查找的数据一定在同一个Page内,但有很大概率,因为有局部性原理。
  • 主要矛盾:IO效率低下的主要矛盾不是单次I/O数据量的大小,而是I/O的次数
3. 有主键的表插入数据时的排序

现象

  • 乱序插入,有序查询:我们向一个具有主键的表中,乱序插入数据,发现数据会自动排序。
  • 结论:数据最终以Page为单位进行管理,而Page是先描述后组织的

4. 单个Page与多个Page

4.1 单个Page

Page的定义

  • Page:一个Page可以看作是一个大的结构体,里面可以放很多数据,也有它自己的属性。
  • 数据承载:一个Page可以承载一部分数据,而一个文件可能很小也可能很大,因此MySQL建立的表可能会是一个或多个Page构成。

Page的特性

  • 大小:在MySQL中,每个Page的大小都是16KB。
  • 双向链表:Page使用prevnext指针构成双向链表,方便管理和遍历。

主键与排序

  • 主键:MySQL会默认按照主键对数据进行排序。
  • 无主键:如果没有主键,默认插入的顺序就是查询时的顺序。

为什么数据库在插入数据时要对其进行排序呢?我们按正常顺序插入数据不是也挺好的吗?

  • 目的:插入数据时排序的目的是优化查询的效率。Page内部的数据记录实质上是一个链表结构,链表的特点是增删快,查询修改慢。因此,有序的结构在查找时更加高效。
  • 优势:有序的数据在查找时从头到尾都是有效查找,没有任何一个查找是浪费的,而且如果运气好,可以提前结束查找过程。

4.2 多个Page

单Page的功能:在查询某条数据时,直接将一整页的数据加载到内存中,以减少硬盘IO次数,从而提高性能。

多Page的管理

  • 数据量大:如果有1千万条数据,需要多个Page来保存,多个Page彼此使用双链表链接起来,每个Page内部的数据也是基于链表的。
  • 线性查找:查找特定一条记录时,需要进行线性查找,效率较低,要遍历一万多条。

页目录的引入

  • 目录的作用:类似于书籍的目录,多花了空间但提高了效率。
  • 所以,目录,是一种“空间换时间的做法”

目录

单Page目录

牺牲page一部分保存数据的空间,把腾出来的空间用来保存目录,这所谓的目录里面只有两个字段

  • 第一个是它所指向起始位置的key值
  • 第二它有一个指针字段指向这条记录的起始位置

所以未来在查找key的时候,不需要在数据记录里面查找了,而是去目录中找

  • 先找到目录中对应key值的所处的起始位置
  • 然后在根据指针找到这条记录
  • 然后根据这条记录在向下遍历。
  • 虽然最后我们依旧需要遍历,但是是一个很小的子序列遍历了。效率也就大大提高了。

那么当前,在一个Page内部,我们引入了目录。比如,我们要查找id=4记录,之前必须线性遍历4次,才能拿到结果。现在直接通过目录2[3],直接进行定位新的起始位置,提高了效率。

现在我们可以再次正式回答上面的问题了,为何通过键值 MySQL 会自动排序?
可以很方便引入目录。

多Page目录

多Page的必要性

  • Page大小固定:MySQL中每一页的大小只有16KB,单个Page大小固定。
  • 数据量增长:随着数据量的不断增大,16KB不可能存下所有的数据,因此需要多个Page来存储数据。

Page的动态管理

  • 自动扩展:在单表数据不断被插入的情况下,MySQL会在容量不足时,自动开辟新的Page来保存新的数据。
  • 组织方式:通过指针的方式,将所有的Page组织起来,形成一个链表结构。

我们每次检索数据的时候,该从哪里开始呢?虽然顶层的目录页少了,但是还要遍历啊?

不用担心,可以再加目录页

多级目录:如果保存数据的Page变得非常多,上层的页目录也会变得非常多

  • 可以通过给上层页目录再加一层目录,形成多级目录结构

这就是传说中的B+树呀!没错,至此,我们已经给我们的表user构建完了主键索引。

随便找一个id=?

我们发现,现在查找的Page数一定减少了,也就意味着IO次数减少了,那么效率也就 提高了。


本篇文章小结:

  • Page:MySQL的基本数据单位,大小为16KB,用于提高I/O效率。
  • 主键与排序:MySQL会默认按照主键对数据进行排序,优化查询效率。
  • 多Page管理:通过页目录和B+树结构,提高多Page间的查找效率。

下篇文章继续讲解

  • B+树:节点不存储数据,叶子节点相连,适合范围查找。
  • 聚簇索引与非聚簇索引:InnoDB使用聚簇索引,MyISAM使用非聚簇索引,各有优劣。

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

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

相关文章

sklearn 实现随机森林分类器 - python 实现

python sklearn 实现随机森林分类器 from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_iris # 加载数据集 irisload_iris() x,yiris.data,iris.target print("x y shape:",x.shape,y.shape) # 创建并训练模型 model Random…

Altium Designer使用技巧(二)

一、创建类 1、按DC键&#xff0c;打开对象类。 2、右键添加一个类。命名为PWR。 3、将所有的电源类&#xff0c;全部添加到新创建的类中&#xff0c;从非成员类中点选到成员类中。 4、右下角点panes ,点PCB。 5、然后在左边单击PWR&#xff0c;点连接&#xff0c;可显示或…

<十六>Ceph mon 运维

Ceph 集群有故障了&#xff0c;你执行的第一个运维命令是什么&#xff1f; 我猜测是ceph -s 。无论执行的第一个命令是什么&#xff0c;都肯定是先检查Mon。 在开始之前我们有必要介绍下Paxos协议&#xff0c;毕竟Mon就是靠它来实现数据唯一性。 一&#xff1a; Paxos 协议 1…

NPOI 操作详解(操作Excel)

目录 1. 安装 NPOI 2. 使用 NPOI 创建新 Excel 文件 3. 设置列宽和行高 1. 设置列宽 2. 设置行高 3. 同时设置列宽和行高 4. 设置统一的行高 5. 设置统一的列宽 6. 应用统一的行高和列宽 4. 合并单元格 5. 设置单元格样式&#xff08;字体、边框、背景色等&#xf…

多处理机调度(李昂学长视频总结)25新增考点

多处理机定义&#xff1a;多处理机指的是某个计算机系统中有多个cpu&#xff0c;在多处理机调度中&#xff0c;多处理机一般指的是共享存储器处理机&#xff0c;其两个或更多的cpu全部共享一个公用的RAM。 根据系统中的处理机相同与否&#xff0c;可将多处理机系统分为如下两类…

少儿编程培训市场突破500亿元:教育新蓝海的崛起与未来展望

近年来&#xff0c;随着科技的迅速发展和家长对教育方式的重视&#xff0c;少儿编程市场成为一片新的蓝海。据最新市场调研报告显示&#xff0c;2024年中国少儿编程培训市场规模已突破500亿元&#xff0c;预计未来五年将持续增长。这一趋势反映了少儿编程教育的迅速崛起&#x…

【大数据学习 | kafka】producer的参数与结构

1. producer的结构 producer&#xff1a;生产者 它由三个部分组成 interceptor&#xff1a;拦截器&#xff0c;能拦截到数据&#xff0c;处理完毕以后发送给下游&#xff0c;它和过滤器不同并不是丢弃数据&#xff0c;而是将数据处理完毕再次发送出去&#xff0c;这个默认是不…

【论文速读】Optimization-based Prompt Injection Attack to LLM-as-a-Judge

基于优化的提示词注入攻击 摘要引言问题描述LLM-as-a-judge威胁模型攻击者知道什么 JUDGEDECEIVER 细节概述生成影子候选回复公式化为优化问题Target-aligned generation lossTarget-enhancement lossAdversarial perplexity loss优化问题 求解优化问题 摘要 LLM-as-a-Judge 利…

人工智能证书合集

本文将对目前市面上主流官方机构颁发的人工智能证书进行整理和介绍&#xff0c;由于整理的证书较多&#xff0c;本文共一万八千多字&#xff0c;请根据自己的考证需求阅读对应部分的内容&#xff0c;希望本文对人工智能行业的从业人员和计划从事人工智能相关岗位工作的人员有所…

Java入门8——二维数组

今天的内容算是数组的收尾~~ 从下次开始就要开始学习类和对象了&#xff0c;冲冲冲&#xff01; 首先二维数组&#xff0c;也很好理解&#xff0c;就是把几个一维数组拼在一起了&#xff0c;我们用代码来熟悉一下~ public class javaSchool {public static void main(String[…

自动售饮料机控制电路的设计

自动售饮料机控制电路的设计 1 设计目的 &#xff08;1&#xff09;熟悉数字电路的应用。 &#xff08;2&#xff09;掌握常常利用逻辑运算器及D触发器的逻辑功能及利用方式。 &#xff08;3&#xff09;熟悉电路仿真软件Multisim 利用。 &#xff08;4&#xff09;了解自动售饮…

高速高精运动控制解决方案亮相2024 NEPCON亚洲电子展!

■展会名称&#xff1a; NEPCON ASIA 2024 亚洲电子生产设备暨微电子工业展览会&#xff08;以下简称“亚洲电子展”&#xff09; ■展会日期 2024年11月6 -8日 ■展馆地点 中国深圳国际会展中心(宝安) ■展位号 11号馆-11A24 11月6日至8日&#xff0c;亚洲电子展将在中…

Flask轻松上手:从零开始搭建属于你的Web应用

目录 一、准备工作 二、安装Flask 三、创建你的第一个Flask应用 创建一个新的Python文件 编写Flask应用代码 运行Flask应用 四、创建一个简单的博客系统 定义路由和文章列表 创建模板文件 运行并测试博客系统 五、使用数据库存储用户信息 安装Flask-SQLAlchemy 修…

STM32开发 —— 新工程创建思路终于清晰了

目 录 工程创建三步法一、工程文件夹创建二、管理工程项三、配置工程参数 工程创建三步法 从ST官网下载好stm32标准库或HAL库&#xff0c;HAL库目录如下。 在Keil开发环境中创建STM32工程&#xff0c;分三大步即可完成工程的创建&#xff1a; 一步&#xff1a;在本地磁盘创建…

Java SpringBoot调用大模型AI构建AI应用

本文是一个用springboot 结合spring mvc 和spring ai alibaba 调用国产大模型通义千问的具体例子&#xff0c;按照这个做能够快速的搞定Java应用的调用。 然后就可以把这类应用泛化到所有的涉及到非结构化数据结构化的场景中。 Spring AI&#xff1a;简化Java中大模型调用的框…

【办公类-04-04】华为助手导出照片视频分类(根据图片、视频的文件名日期导入“年-月-日”文件夹中,并转移到“年-月”文件中整理、转移到“年”文件夹中整理)

背景需求 最近带班&#xff0c;没有时间整理照片&#xff0c;偶尔导一次&#xff0c;几个月的照片。发现用电脑版“华为手机助手“中的WLAN连接”与华为手机的“华为手机助手”连接&#xff0c;速度更快、更稳定&#xff0c;不会出现数据线连接时碰碰就断网的问题 1、先打开电…

电脑没有下载声卡驱动怎么办?电脑声卡驱动安装方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到电脑没有声音的问题&#xff0c;这往往与声卡驱动缺失或损坏有关。声卡驱动是连接电脑硬件&#xff08;声卡&#xff09;与操作系统之间的桥梁&#xff0c;确保音频信号能够正常输入输出。那么&#xff0c;当电脑没有声卡驱动…

MYSQL死锁真实案例

​最近例行巡检时候发现一个死锁,阿里云RDS FOR MYSQL 8.0.X! 虽然阿里云的死锁页面看起来比较友好,不过跟社区版一样只是显示事务最后一条死锁SQL和相关的信息.一不小心对初级MYSQL DBA来说,深深地误导,浪费大量时间研究这两个SQL怎么发生了死锁! 阿里云RDS默认情况下审计没有…

【Spring】Spring Boot 日志(8)

本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 目录 本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 …

饿了么数据库表设计

有商家表、商品表、商品规格表、购物车表&#xff0c;不难分析出表是不够全面的。 (1)首先分析需要补充的表 1.对于购物车而言肯定有对应的用户&#xff0c;因此要添加一个用户表。 2.商品规格是冷&#xff0c;热&#xff0c;半分糖、全糖&#xff0c;对于冷热和半分糖是可以分…