MySQL进阶之(五)InnoDB数据存储结构之表空间

news2024/11/17 4:54:30

五、InnoDB数据存储结构之表空间

  • 5.1 数据页加载的三种方式
    • 5.1.1 内存读取
    • 5.1.2 随机读取
    • 5.1.3 顺序读取
  • 5.2 区
    • 5.2.1 为什么要有区?
    • 5.2.2 碎片区
    • 5.2.3 区的分类
  • 5.3 段
  • 5.4 表空间
    • 5.4.1 独立表空间
    • 5.4.2 系统表空间

在数据页结构中提到过,页的上层结构中,还存在着区、段、表空间的概念,它们之间的关系如图所示:
在这里插入图片描述

  • 行(row):数据库中的数据都是按行存储的,行记录根据不同的行格式,有不同的存储结构。
  • 页(page):记录是按行存储的,但是数据库的读取并不是以行为单位的,而是以页为单位,每页的大小为 16KB。如果每次读取数据只能读取一行、处理一行数据,那么频繁的 I/O 操作会使效率非常低。
  • 区(extent):B+Tree 的每一层节点之间都是通过双向链表链接的,以页为单位,相邻的两个页之间位置并不是连续的(逻辑上连接),可能离得非常远,如果数据量大的情况下,查询会产生大量的随机 I/O(效率低)。为了解决这个问题,为某个索引分配空间的时候就按照区为单位,一个区的大小为 1MB,对于 16KB 大小的页来说,连续的 64 个页划分为一个区(1MB / 16KB = 1024KB / 16KB = 64),这样就使得相邻的页的物理位置也是相邻的,就可以使用顺序 I/O 了
  • 段(segment):表空间由多个段组成的,段是由多个区组成的。段一般可分为数据段、索引段和回滚段等。
    • 数据段:存放 B+Tree 叶子节点区的集合
    • 索引段:存放 B+Tree 非叶子节点区的集合
    • 回滚段:存放回滚数据区的集合(MVCC 就是利用了回滚段实现了多版本查询控制)
  • 表空间(Tablespace):是一个逻辑容器,表空间存储的对象是段,在一个空间中可以有一个段或多个段,但是一个段只能属于一个表空间。

5.1 数据页加载的三种方式

5.1.1 内存读取

如果数据存储在内存中,直接从内存中读取数据:
在这里插入图片描述

5.1.2 随机读取

如果数据没有在内存中,就需要在磁盘上对该页进行查找。在读取一个页的过程中,可能有五分之三的时间是磁盘实际繁忙时间(包括寻道和半圈旋转的时间),十分之三的时间是排队时间,十分之一是传输时间,将页从磁盘服务器缓冲区传输到数据库缓冲区中。

在这里插入图片描述

5.1.3 顺序读取

顺序读取其实是一种批量读取的方式,因为我们请求的数据在磁盘上往往都是相邻存储的,顺序读取可以帮我们批量读取页面。这样的话,一次性加载到缓存池中就不需要再对其他页面单独进行磁盘 I/O 操作了。

如果一个磁盘的吞吐量是 40MB/S,那么对于一个 16KB 大小的页来说,一次可以顺序读取 2560(40MB/16KB)个页,相当于一个页的读取时间为 0.4ms。采用批量读取的方式,即使是从磁盘上进行读取,效率也比从内存中只单独读取一个页的效率要高。

5.2 区

5.2.1 为什么要有区?

B+Tree 的每一层节点之间都是通过双向链表连接的,以页为单位分配存储空间,相邻的两个页之间的位置可能并不连续,反而离得非常远。

在 B+Tree 索引的范围查询时,只需要定位到最左边的记录和最右边的记录,然后沿着双向链表一直扫描就可以了,而如果链表中相邻的两个数据页的物理位置相差的很远,就需要进行多次的随机 I/O 操作。

磁盘的速度和内存的速度相差好几个数量级,随机 I/O 是非常慢的。

所以,就要想办法使用顺序 I/O,尽量让链表中相邻的页的物理位置也相邻,这就引入了区的概念:一个区在物理上就是连续的 64 个页(1MB / 16KB = 1024KB / 16KB = 64))。

在表中数据非常大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位分配,甚至在表中的数据特别多的时候,可以一次性分配多个连续的区。这样可能会造成一点空间上的浪费(数据不足以填充满整个区),但是从性能上来讲,可以消除很多随机 I/O。所以从这点上来说,功大于过,以空间换时间。

总之,区的出现是为了尽量减少随机 I/O

5.2.2 碎片区

默认情况下,一个使用 InnoDB 存储引擎的表只有一个聚簇索引,一个索引会生成 2 个段:非叶子节点段和叶子节点段。而段是以区为单位申请存储空间的,一个区默认占用 1MB(64 * 16KB = 1024KB)存储空间,所以一个表默认情况下存储空间至少为 2MB。那么,设想一下几个问题:

  1. 默认情况下,一个只存放了几条记录的小表是否也需要 2MB 的存储空间?
  2. 以后每添加一个索引,都要多申请 2MB 的存储空间么?

这对于存储记录比较少的表来说简直就是天大的浪费。

这个问题的原因就在于:我们目前讨论的区都是非常纯粹的,也就是一个区被整个分配给某一个段,或者说区中的所有页面都是为了存储同一个段的数据而存在的。即使段的数据填不满区中所有的页面,剩下的页面也不能用于存储其他段的数据了,这样就严重造成了空间浪费。

所以,针对【以完整的区为单位分配给某个段时,对于数据量较小的表来说太浪费存储空间】这种情况,设计 InnoDB 的大叔提出了碎片区的概念。

在一个碎片区中,并不是所有的页都是为了存储同一个段的数据而存在的,碎片区中的页可以用于不同的目的,比如:有些页属于段 A,有些页属于段 B,有些页甚至不属于任何段。碎片区直属于表空间,并不属于任何一个段。

有了碎片区的概念后,为某个段分配存储空间的策略是这样的:

  • 在刚开始向表中插入数据时,段是从某个碎片区以单个页面为单位来分配存储空间的。
  • 当某个段已经占用了 32 个碎片区页面之后,就会以完整的区为单位来分配存储空间(原先占用的碎片区页面并不会被复制到新申请的完整的区中)。

所以,段就是一些零散的页面以及一些完整的区的集合

5.2.3 区的分类

区大体上可以分为 4 种类型:

  1. 空闲的区(FREE): 现在还没有用到这个区的任何页面。
  2. 有剩余空间的碎片区(FREE_FRAG): 表示碎片区中还有可用的页面。
  3. 没有剩余空间的碎片区(FULL_FRAG): 表示碎片区中所有页面都被使用,没有空间页面。
  4. 附属于某个段的区(FSEG): 每个索引都可以分为叶子节点段(数据段)和非叶子节点段(索引段)。
    处于 FREE、FREE_FRAG、FULL_FRAG这三种状态的区都是独立的,而处于 FSEG状态的区是附属于某个段的。

5.3 段

对于范围查询,其实是对 B+Tree 叶子节点中的记录进行顺序扫描,而如果不区分叶子节点和非叶子节点,统一把节点页面放在申请到的区中进行范围扫描,扫描效率相比叶子节点就会低很多。所以 InnoDB 对 B+Tree 的叶子节点和非叶子节点进行了区别对待,分别放在各自独立的区中。

这样在创建一个索引时,会生成两个段:叶子节点段和非叶子节点段。

常见的段有:数据段、索引段、回滚段。

  • 数据段:存放 B+Tree 叶子节点
  • 索引段:存放 B+Tree 非叶子节点
  • 回滚段:存放回滚数据

在 InnoDB 存储引擎中,对段的管理都是由存储引擎本身完成的,DBA 不能也没有必要对其进行控制,这从一定程度上简化了 DBA 对于段的管理。

段其实不是表空间中某一个连续的物理区域,而是一个逻辑上的概念,由若干个零散的页面(不归属与任何区,直接归属于表空间)一些完整的区组成。

5.4 表空间

表空间可以看作是 InnoDB 存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。它是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以由一个或多个段,但是一个段只能属于一个表空间。

表空间数据库由一个或多个表空间组成,表空间从管理上可以划分为:

  • 系统表空间(System TableSpace)
  • 独立表空间(File-per-table TableSpace)
  • 撤销表空间(Undo TableSpace)
  • 临时表空间(Temporary TableSpace)

5.4.1 独立表空间

每张表都有一个独立表空间,也就是数据和索引信息都会保存在自己的独立表空间中。独立表空间(单表)可以在不同的数据库之间进行迁移。

表空间可以回收,命令 DROP TABLE_NAME 操作可自动回收表空间,其他情况,表空间不能自动回收。另外,DELETE FROM TABLE_NAME 操作是假删除数据,数据底层只是被标记为删除了,但实际上还占据存储空间,所以空间不会被回收。

如果对于统计分析或者是日志表,删除大量数据后可以通过命令 alter table table_name engine=innodb;回收不用的空间(重置 InnoDB 索引结构,会重新分配存储空间,空闲的空间会被回收)。对于使用独立表空间的表,不管怎么删除,表空的碎片都不会太影响性能,而且还有机会被处理。

独立表空间由段、区、页组成。

真实表空间对应的文件大小

⭐ MySQL 5.7

在 MySQL 5.7 中,每新建一张表,在数据库的目录中都会新增两个文件:.frm 和 .idb 文件。

在这里插入图片描述
.frm 存放表结构文件默认大小为 9KB,还不到一个页面的大小。

.ibd 存放数据文件默认大小为 96KB(98304 byte/1024 = 96KB),等于 96KB / 16KB = 6 个页面。

加到一起还不到 7 个页面大小,因为表空间初始化没有数据,所以占用空间很小。但是 .ibd 文件是自扩展的,随着表中的数据增多,表空间对应的文件也会逐渐增大。

⭐ MySQL 8.0

在 MySQL 8.0 中,每新建一张表,在数据库的目录中都会新增一个 .ibd 文件,删除了 .frm 文件。

在这里插入图片描述
.idb 存放数据文件默认大小为 114688byte(114688byte / 1024 = 112KB),等于 112KB / 16KB = 7 个页面大小,比 MySQL 5.7 多了一个页面大小,是因为 MySQL 8.0 将表结构和数据都存储在了 .ibd文件中。

查看 InnoDB 表空间类型

是否使用独立表空间可以通过一个全局参数 innodb_file_per_table 配置:

  • 设置为 1 就代表使用独立表空间(后缀 table_name.idb中)
  • 设置为 0 代表使用系统表空间(存储在共享表空间文件中ibdata1中)。
    从 MySQL 5.6.6 版本之后,innodb_file_per_table 默认值就为 1 了,因此此后的版本,表数据默认都是存储在独占表中的。
# MySQL 5.7 和 MySQL 8.0 查看结果
show variables like 'innodb_file_per_table';

在这里插入图片描述

5.4.2 系统表空间

每当我们向表中插入一条记录的时候,MySQL 的校验过程如下:

  1. 先要校验一下插入语句对应的表存不存在?
  2. 插入的列和表中的列是否符合?

如果语法没有问题,还需要知道该表的聚簇索引和所有二级索引的根页面是在哪个表空间下的哪个索引段中,然后把记录插入到对应索引的 B+Tree 中。

所以 MySQL 除了保存我们插入的用户记录之外,还需要保存许多额外的信息,例如下面的这些数据:

● 某个表属于哪个表空间,表里边有多少列
● 表对应的每一个列的类型是什么
● 该表有多少索引,每个索引对应哪几个字段,该索引对应的根页面在哪个表空间的哪个页面
● 该表有哪些外键,外键对应哪个表的哪些列
● 某个表空间对应文件系统上文件路径是什么
● ………………

这些数据并不是我们使用 INSERT 语句插入的用户记录数据,而是为了更好的管理我们这些用户数据不得已才引入的一些额外数据,我们称这些数据为元数据

InnoDB 存储引擎特意定义了一些列的内部系统表(internal system table)来记录这些元数据:
在这里插入图片描述
这些系统表也被称为数据字典 ,它们都是以 B+Tree 的形式保存在系统表空间的某些页面中,其中

  • SYS_TABLES
  • SYS_COLUMNS
  • SYS_INDEXES
  • SYS_FIELDS

这四个表尤其重要,称之为基本系统表(basic system tables)

⭐ SYS_TABLES 表结构
在这里插入图片描述
⭐ SYS_COLUMNS 表结构
在这里插入图片描述
⭐ SYS_INDEXES 表结构
在这里插入图片描述
⭐ SYS_FIELDS 表结构
在这里插入图片描述
注意:用户是不能直接访问 lnnoDB 的这些内部系统表,除非直接去解析系统表空间对应文件系统上的文件。不过考虑到查看这些表的内容可能有助于大家分析问题,所以在系统数据库 information_schema 中提供了一些以 innodb_sys开头的表。

MySQL 8.0 中是不存在以 innodb_sys 开头的表的。

MySQL 5.7 中操作如下:

mysql> use information_schema;
Database changed
mysql> show tables like 'innodb_sys%';
+--------------------------------------------+
| Tables_in_information_schema (innodb_sys%) |
+--------------------------------------------+
| INNODB_SYS_DATAFILES                       |
| INNODB_SYS_VIRTUAL                         |
| INNODB_SYS_INDEXES                         |
| INNODB_SYS_TABLES                          |
| INNODB_SYS_FIELDS                          |
| INNODB_SYS_TABLESPACES                     |
| INNODB_SYS_FOREIGN_COLS                    |
| INNODB_SYS_COLUMNS                         |
| INNODB_SYS_FOREIGN                         |
| INNODB_SYS_TABLESTATS                      |
+--------------------------------------------+
10 rows in set (0.01 sec)

在 information_schema 数据库中的这些以 INNODB_SYS 开头的表并不是真正的内部系统表(内部系统表就是我们上边以 SYS 开头的那些表),而是在存储引警启动时读取以 SYS 开头的系统表,然后填充到以 INNODB_SYS 开头的表中。以 INNODB_SYS 开头的表和以 SYS 开头的表中的字段并不完全一样,但足够供我们参考了。

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

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

相关文章

RN开发搬砖经验之-如何处理FlashList组件加载后调用scrollToIndex没有滚动指定位置

前言 如题,这里只能说是处理,起正向作用的临时方案,因为我也着实没搞懂这个BUG的具体原因,看github上有提相关的issuesFor long lists with different item types scrollToIndex does not work reliable,但看官方没有…

PLC的FC与FB模块程序的功能解析

前文讲了在西门子系列的PLC中四个程序模块的描述,从S7-1200PLC开始就有FC和FB程序块了,但在使用的时候,一些使用者还是不好理解,以至于不知道该如何选择。今天,我们就用大白话的方式给大家讲解FC与FB的功能。 1、FC与…

前端学习之列表标签

目录 有序列表 结果 无序标签 结果 数据标签 结果 有序列表 &#xff08;注&#xff1a;注释是解释&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title> </…

Image Demoireing with Learnable Bandpass Filters

一、简介 标题:Image Demoireing with Learnable Bandpass Filters(https://openaccess.thecvf.com/content_CVPR_2020/papers/Zheng_Image_Demoireing_with_Learnable_Bandpass_Filters_CVPR_2020_paper.pdf) 期刊:CVPR 时间:2020 作者:Bolun Zheng, Shanxin Yuan, …

Google浏览器122.下载驱动

打开网址&#xff1a;Chrome for Testing availability (googlechromelabs.github.io) 选择stable 选择对应的驱动就行

前后端交互理解 简易表白墙(servlet)

前后端交互理解 简易表白墙&#xff08;servlet&#xff09; 文章目录 前后端交互理解 简易表白墙&#xff08;servlet&#xff09;后端核心内容前后端交互接口约定后端代码展示 上期介绍过 Servlet API &#xff0c;本篇文章目的是借助 servlet 做出一个完整的网站。在一个网站…

Spring Boot 面试题及答案整理,最新面试题

Spring Boot中的自动配置是如何工作的&#xff1f; Spring Boot的自动配置是其核心特性之一&#xff0c;它通过以下方式工作&#xff1a; 1、EnableAutoConfiguration注解&#xff1a; 这个注解告诉Spring Boot开始查找添加了Configuration注解的类&#xff0c;并自动配置它们…

怎么看待Groq

用眼睛看。 就是字面上的意思用眼睛看。 我属于第一波玩到的,先给大家一个直观的印象,Groq到底有多快。 目前Groq只能选Llama的70b,和Mixtral的MoE,那我选7*8的这个MoE模型来实验。 这么好些字大概花了不到1秒,流式响应,其实是不是流式已经没那么重要了 ,然后看每秒Toke…

第二十二周周报

论文研读&#xff1a;Camera Distance-aware Top-down Approach for 3D Multi-person Pose Estimation from a Single RGB Image 粗读10篇文献。 通过图2 我可以知道这个论文大概实现的这个姿态估计效果的方法&#xff0c;首先是把图片输入到DetectNet网络&#xff0c;该网络…

也就老炮知道:UI设计师和前端,以前叫美工和切片。

过去&#xff0c;UI设计师常常被称为美工&#xff0c;而前端开发人员被称为切片工。这是因为在过去的网页设计中&#xff0c;UI设计师主要负责设计网页的外观和用户界面&#xff0c;包括颜色、布局、图标等&#xff0c;类似于传统的美工工作。而前端开发人员则负责将UI设计师提…

搭建nacos集群,并通过nginx实现负载均衡

nacos、eureka、consul、zookeeper等都是常用的微服务注册中心&#xff0c;这篇文章详细介绍一下在Ubuntu操作系统上搭建一个nacos的集群&#xff0c;以及通过nginx的反向代理功能实现nacos的负载均衡。 目录 一、安装nacos 1、安装nacos 2、修改nacos配置文件 3、创建naco…

Cocos Creator 2d光照

godot游戏引擎是有2d光照的&#xff0c;用起来感觉还是很强大的&#xff0c;不知道他是怎么搞的&#xff0c;有时间看看他们怎么实现的。 之前一直以为cocos社区里面没有2d光照的实现&#xff0c;偶然看到2d实现的具体逻辑&#xff0c;现在整理如下&#xff0c; 一&#xff1…

Spring Boot 中解决跨域的多种方式

Spring Boot 中解决跨域的多种方式 《踏过跨域障碍&#xff1a;Spring Boot 中解决跨域的多种方式》摘要引言正文何为跨域跨域问题出现特征方式一&#xff1a;使用 CrossOrigin 注解方式二&#xff1a;自定义 WebMvcConfigurer方式三&#xff1a;使用 Filter 进行跨域配置 结论…

java之lombok

Lombok是一个实用的java类库&#xff0c;能通过注解的形式自动生成构造器&#xff0c; getter setter equsls hashcode tostring等方法 并且可以自动化生成日志变量&#xff0c;简化java开发&#xff0c;提高效率 作用 导入 <dependency><groupId>org.projectlomb…

集合框架(一)Set系列集合

Set<E>是一个接口 特点 无序&#xff1a;添加数据的顺序和获取出的数据顺序不一致&#xff1b;不重复&#xff0c;无索引 注意&#xff1a;Set要用到的常用方法&#xff0c;基本上就是collection提供的!自己几乎没有额外新增一些常用功能! HashSet集合的底层原理 前置知…

我们的一生都是在挤火车。

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 昨天从燕郊坐火车回石家庄&#xff0c;由于赶上元旦假期&#xff0c;所有高铁票都售罄&#xff0c;一张普通火车票&#xff0c;还是一周前就买才买到的。 从燕郊站&#xff0c;到北京站&#xff0c;然后地铁去北京西站…

C++虚继承的一些细节

C虚继承的一些细节 何时使用虚继承普通继承的类对象布局虚继承类对象布局虚函数表指针虚函数表内容 何时使用虚继承 看代码&#xff0c;代码主要是菱形继承&#xff0c;base里面的成员变量会存在二义性 #include<iostream> using namespace std;class base { public:in…

【机器学习】从线性回归模型看一个简单的成本函数

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;机器学习&#x1f338;今日语录&#xff1a;事情不做&#xff0c;越想越难&#xff1b;事情做了&#xff0c;越做越容易。 从线性回归模型看一个简单的成本函数 &#x1f33c;引入&#xff1a;模型…

基于SpringBoo的火车订票管理系统(程序+文档+数据库)

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一、研究背景…

2024年【G2电站锅炉司炉】考试题及G2电站锅炉司炉证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【G2电站锅炉司炉】考试题及G2电站锅炉司炉证考试&#xff0c;包含G2电站锅炉司炉考试题答案和解析及G2电站锅炉司炉证考试练习。安全生产模拟考试一点通结合国家G2电站锅炉司炉考试最新大纲及G2电站锅炉司炉考…