MYSQL08_页的概述、内部结构、文件头、文件尾、最大最小记录、页目录、区段表

文章目录

  • ①. 页的概述、大小
  • ②. 页的内部结构
  • ③. 第一部分 - 文件头
  • ④. 第一部分 - 文件尾
  • ⑤. 第二部分 - 空闲、用户记录、最大最小
  • ⑥. 第三部分 - 页目录
  • ⑦. 第三部分 - 页面头部
  • ⑧. 从数据页角度看B+树
  • ⑨. 区、段和表、碎片区

①. 页的概述、大小

  • ①. 数据库的存储结构:页
  1. 索引结构给我们提供了高效的索引方式,不过索引信息以及数据记录都是保存在文件上的,确切来说是存储在页结构中。另一方面,索引是在存储引擎中实现的,MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同的存储引擎中存放的格式一般是不同的,甚至有的存储引擎Memory都不用磁盘来存储数据
  2. 由于InnoDB是MySQL的默认存储引擎,所以本章节讲解InnoDB存储引擎的数据存储结构
  • ②. 磁盘与内存交互的基本单位:页
  1. InnoDB将数据划分为若干个页,InnoDB中页的默认大小为16KB
  2. 以页作为磁盘和内存之间交互的基本单位,也就是一次最少从磁盘中读取16KB的内容到内存中,一次最少把16KB的内容刷新到磁盘中
  3. 在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载。也就是说数据库管理存储空间的基本单位是页,数据库I/O操作的最小单位也是页。一个页中可以存储多个行记录
    注意:记录是按照行来储存的,但是数据库的读取并不以行为单位,否则一次读取(也就是一次I/O操作),只能处理一行数据,效率会非常的低
  • ③. 页结构概述
  1. 页a、页b、页c,这些页可以不在物理结构上相连,只要通过双向链表相关联即可
  2. 每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表,每个数据页都会为存储在它里边的记录生成一个页目录
  3. 在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽
    在这里插入图片描述
  • ④. 页的大小
    不同数据库管理系统的页大小不同,MySQL的InnoDB存储引擎中,默认的页大小是16KB
    SQL Server中页的大小为8kb,而在Oracle中我们用术语"块"来代表页,Oracke支持的块大小为2kb、4kb、8kb、16kb、32kb、64kb
mysql> show variables like '%innodb_page_size%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
  • ⑤. 页的上层结构,在数据库中还存在着区、段、和表空间的概念
  1. 区(Extent)是比页大一级的存储结构,在InnoDB存储引擎中,一个区会分配64个连续的页。因为InnoDB中的页大小默认是16KB,所以一个区的大小是64 * 16KB = 1MB
  2. 段(Segment)由一个或多个区组成,区在文件系统是一个连续分配的空间(在InnoDB中是连续的64个页),不过在段中不要求区与区之间是相邻的。段是数据库中分配单位,不同类型数据库对象以不同的段形式存在。当我们创建数据表、索引的时候,就会响应创建对应的段,比如创建一张表时会创建一个表段,创建一个索引时会创建一个索引段
  3. 表空间(Tablespace)是一个逻辑容器,表空间储存的对象是段,在一个表空间中可以有一个或多个段,但是一个段只能属于一个表空间。数据库由一个或多个表空间组成,表空间从管理上可以划分为系统表空间、用户表空间、撤销表空间、临时表空间
    在这里插入图片描述

②. 页的内部结构

  • ①. 页按照类型划分,常见的有数据页(保存B+树节点)、系统页、Undo页和事务数据页等。数据页是我们最常使用的页,页结构示意图如下:
    在这里插入图片描述
  • ②. 数据页16KB大小的存储空间被划分为七个部分,分别是文件头、页头、最大最小记录、用户记录、空闲空间、页目录和文件尾,如下图所示

在这里插入图片描述

③. 第一部分 - 文件头

  • ①. File Header:描述各种页的通用信息。比如页的编号、其上一页、下一页是谁等、大小为38字节

  • ②. File Header文件头部具体构成
    在这里插入图片描述

  • ③. FIL_PAGE_OFFSET:每一个页都有一个单独的页号,就跟你的身份证号码一样,InnoDB通过页号可以唯一定位一个页

  • ④. FIL_PAGE_TYPE:代表当前页的类型
    在这里插入图片描述

  • ⑤. FIL_PAGE_PREV和FIL_PAGE_NEXT
    InnoDB都是以页为单位存放数据的,如果数据分散到多个不连续的页中存储的话需要把这些页关联起来,FIL_PAGE_PREV和FIL_PAGE_NEXT就分别代表本页的上一个和下一个页的页号。这样通过建立一个双向链表把许许多多的页就都串联起来了,保证这些页之间不需要是物理上的连续,而是逻辑上的连续
    在这里插入图片描述

  • ⑥. FIL_PAGE_SPACE_OR_CHKSUM:代表当前页面的校验和checksum

  1. 文件头部和文件尾部都有属性:FIL_PAGE_SPACE_OR_CHKSUM
  2. 什么是校验和?对于一个很长的字节串来说,我们会通过某种算法来计算一个比较短的值来代表这个很长的字节串,这个比较短的值就称为校验和
  3. 在比较两个很长的字节串之前,先比较这两个长字节串的校验和,如果校验和都不一样,则两个长字节串肯定是不同的,所以省去了直接比较两个比较长的字节串的时间损耗
  • ⑦. 校验和的作用
  1. InnoDB存储引擎以页为单位把数据加载到内存中处理,如果该页中的数据在内存中被修改了,那么在修改后的某个时间需要把数据同步到磁盘中。但是在同步了一半的时候断电了,造成了该页传输的不完整
  2. 为了检测一个页是否完整也就是在同步的时候有没有发生只同步一半的尴尬情况,这时可以通过文件尾的校验和checksum值与文件头的校验和做比对,如果两个值不相等则证明页的传输有问题,需要重新进行传输,否则认为页的传输已经完成
  • ⑧. 校验和举例子
  1. 每当一个页面在内存中修改了,在同步之前就要把它的校验和算出来,因为File Header在页面的前边,所以校验和会被首先同步到磁盘,当完全写完时,校验和也会被写到页的尾部,如果完全同步成功,则页的首部和尾部的校验和应该是一致的
  2. 如果写了一半儿断电了,那么在File Header中的校验和就代表着已经修改过的页,而在File Trailer中的校验和代表着原先的页,二者不同则意味着同步中间出了错。这里,校验方式就是采用 Hash 算法进行校验
  • ⑨. FIL_PAGE_LSN:页面被最后修改时对应的日志序列位置英文名是:Log Sequence Number

④. 第一部分 - 文件尾

  • ①. 大小8字节
  1. 前4个字节代表页的校验和:这个部分是和File Header中的校验和相对应的
  2. 后4个字节代表页面被最后修改时对应的日志序列位置LSN:这个部分也是为了校验页的完整性的,如果首部和尾部的LSN值校验不成功的话,就说明同步过程出现了问题
  • ②. 文件头部和文件尾部都有属性:FIL_PAGE_SPACE_OR_CHKSUM

⑤. 第二部分 - 空闲、用户记录、最大最小

  • ①. 页的主要作用是存储记录,所以 “最大和最小记录” 和 “用户记录” 部分占了页结构的主要空间
    在这里插入图片描述
  • ②. Free Space (空闲空间)
    我们自己存储的记录会按照指定的行格式存储到User Records部分。但是在一开始生成页的时候,其实并没有User Records这个部分,每当我们插入一条记录,都会从Free Space部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到User Records部分,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了

在这里插入图片描述

  • ③. User Records中的这些记录按照指定的行格式一条一条摆在User Records部分,相互之间形成单链表

  • ④. Infimum + Supremum(最小最大记录)
    InnoDB规定的最小记录与最大记录这两条记录的构造十分简单,都是由5字节大小的记录头信息和8字节大小的一个固定的部分组成的,如图所示
    在这里插入图片描述
    在这里插入图片描述

⑥. 第三部分 - 页目录

  • ①. 为什么需要页目录?
    在页中,记录是以单向链表的形式进行存储的。单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索。因此在页结构中专门设计了页目录这个模块,专门给记录做一个目录,通过二分查找法的方式进行检索,提升效率

  • ②. 需求:根据主键值查找页中的某条记录,如何实现快速查找呢?

SELECT * FROM page_demo WHERE c1 = 3;

方式1:顺序查找
从Infimum记录(最小记录)开始,沿着链表一直往后找,总有一天会找到(或者找不到),在找的时候还能投机取巧,因为链表中各个记录的值是按照从小到大顺序排列的,所以当链表的某个节点代表的记录的主键值大于你想要查找的主键值时,你就可以停止查找了,因为该节点后边的节点的主键值依次递增(如果一个页中存储了非常多的记录,这么查找性能很差)
方式2:使用页目录,二分法查找

  1. 将所有的记录分成几个组,这些记录包括最小记录和最大记录,但不包括标记为“已删除”的记录。
  2. 第1组,也就是最小记录所在的分组只有1个记录;
    最后一组,就是最大记录所在的分组,会有1-8条记录;
    其余的组记录数量在4-8条之间
    这样做的好处是,除了第1组(最小记录所在组)以外,其余组的记录数会尽量平分
  3. 在每个组中最后一条记录的头信息中会存储该组一共有多少条记录,作为n_owned字段。
  4. 页目录用来存储每组最后一条记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量也被称之为槽(slot),每个槽相当于指针指向了不同组的最后一个记录
    在这里插入图片描述
  • ③. 现在的page_demo表中正常的记录共有6条,InnoDB会把它们分成两组,第一组中只有一个最小记录,第二组中是剩余的5条记录。如下图
  1. 现在页目录部分中有两个槽,也就意味着我们的记录被分成了两个组,槽1中的值是112,代表最大记录的地址偏移量(就是从页面的0字节开始数,数112个字节);槽0中的值是99,代表最小记录的地址偏移量
  2. 注意最小和最大记录的头信息中的n_owned属性
    最小记录的n_owned值为1,这就代表着以最小记录结尾的这个分组中只有1条记录,也就是最小记录本身
    最大记录的n_owned值为5,这就代表着以最大记录结尾的这个分组中只有5条记录,包括最大记录本身还有我们自己插入的4条记录

在这里插入图片描述
在这里插入图片描述

  • ④. 在一个数据页中查找指定主键值的记录的过程分为两步(非常重要)
  1. 通过二分法确定该记录所在的槽,并找到该槽所在分组中主键值最小的那条记录
  2. 通过记录的next_record属性遍历该槽所在的组中的各个记录

⑦. 第三部分 - 页面头部

  • ①. 为了能得到一个数据页中存储的记录的状态信息,比如本页中已经存储了多少条记录,第一条记录的地址是什么,页目录中存储了多少个槽等等,特意在页中定义了一个叫Page Header的部分,这个部分占用固定的56个字节,专门存储各种状态信息
    在这里插入图片描述

  • ②. PAGE_DIRECTION:假如新插入的一条记录的主键值比上一条记录的主键值大,我们说这条记录的插入方向是右边,反之则是左边。用来表示最后一条记录插入方向的状态就PAGE_DIRECTION

  • ③. PAGE_N_DIRECTION:假设连续几次插入新记录的方向都是一致的,InnoDB会把沿着同一个方向插入记录的条数记下来,这个条数就用PAGE_N_DIRECTION这个状态表示。当然,如果最后一条记录的插入方向改变了的话,这个状态的值会被清零重新统计

⑧. 从数据页角度看B+树

  • ①. 一颗B+树按照节点类型可以分成两部分
  1. 叶子节点,B+树最底层的节点,节点的高度为0,储存行记录
  2. 非叶子节点,节点的高度大于0,储存索引键和页面指针,并不储存行记录本身
    在这里插入图片描述
  • ②. B+树是如何进行记录检索的呢
    从B+树的跟几点开始,逐层检索,在哪个目录项里面,进行定位到具体的页,将数据页加载到内存中,页目录中的槽(slot)采用二分查找的方式找到一个粗略的记录分组,找到最小的那条记录,通过next_record遍历查找记录

  • ③. 普通索引和唯一索引在查询效率上有什么不同?
    唯一索引就是在普通索引上增加了约束性,也就是关键字唯一,找到了关键字就停止检索。而普通索引,可能会存在用户记录中的关键字相同的情况,根据页结构的原理,当我们读取一条记录的时候,不是单独将这条记录从磁盘中读出去,而是将这个记录所在的页加载到内存中进行读取。InnoDB储存引擎的页大小为16KB,在一个页中可能存储着上千条记录,因此在普通索引的字段上进行查找页就是在内存中多几次"判断下一条记录"的操作,对于CPU来说,这些操作所消耗的时间是可以忽略不计的。所以对一个索引字段进行检索,采用普通索引还是唯一索引在检索效率上基本上没差别

⑨. 区、段和表、碎片区

  • ①. 为什么要有区?
  1. B+树的每一层中的页都会形成一个双向链表,如果是以页为单位来分配存储空间的话,双向链表相邻的两个页之间的物理位置可能离的非常远,如果需要范围查询的话只需要定位最左边和最右边的记录,沿着双向链表一直扫描即可,而如果两个页之间的物理位置隔得非常远,就是所谓的随机I/O,这是非常慢的,所以应该尽量让链表中相邻页的物理位置页相邻,这样进行范围查询时才可以使用所谓的顺序I/O
  2. 这就引入了的概念,一个区就是在物理位置上连续的64个页,因为InnoDB的页大小默认是16KB,所以一个区的大小是1MB。在表中数据量大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位分配,甚至在表中数据特别多的时候,可以一次性分配多个连续的区。虽然可能造成一点点空间的浪费,但是从性能角度看,可以消除很多随机I/O

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

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

相关文章

计算机服务器中了360后缀勒索病毒怎么办?360后缀勒索病毒解密步骤

网络技术的不断应用与发展,为企业的生产运营提供了极大便利,利用网络可以开展各项工作业务,可以大大提高企业的生产效率,然而,网络是一把双刃剑,在为企业提供便利的同时,也为企业的数据安全带来…

【C 数据结构】单链表

文章目录 【 1. 基本原理 】1.1 链表的节点1.2 头指针、头节点、首元节点 【 2. 链表的创建 】2.0 创建1个空链表(仅有头节点)2.1 创建单链表(头插入法)*2.2 创建单链表(尾插入法) 【 3. 链表插入元素 】【…

下载好了annaconda,但是在创建一个新的Conda虚拟环境报错

文章目录 问题描述:解决方案1.生成一个配置文件 问题总结 问题描述: ProxyError(MaxRetryError(“HTTPSConnectionPool(host‘repo.anaconda.com’, port443): Max retries exceeded with url: /pkgs/pro/win-64/repodata.json.bz2 (Caused by ProxyErr…

【深度学习实战(1)】如何使用argparse模块设置自己的训练参数

一、argparse模块用法 1、argparse是一个python模块,用途是:命令行选项、参数和子命令的解释。 2、argparse库下载:pip install argparse 3、使用步骤: 导入argparse模块,并创建解释器 添加所需参数 解析参数 二、…

Ubuntu去除烦人的顶部【活动】按钮

文章目录 一、需求说明二、打开 extensions 网站三、安装 GNOME Shell 插件四、安装本地连接器五、安装 Hide Activities Button 插件六、最终效果七、卸载本地连接器命令参考 本文所使用的 Ubuntu 系统版本是 Ubuntu 22.04 ! 一、需求说明 使用 Ubuntu 的过程中,屏…

容器镜像进阶

Dockerfile 编写注意事项: 选择合适的基础镜像,没必要追求镜像的绝对大小。 alpine镜像不推荐,尤其是编译型业务,因为alpine镜像内置的musl libc库与标准的glibc不一样。 如果就是想使用alpine镜像,推荐多阶段构建&am…

003Node.js创建第一个web服务

如果用PHP来编写后端代码,需要用Apache或者Nginx的服务器,来处理客户的请求响应。对于Node.js时,不仅实现了应用,同时还实现了整个HTTP服务器. 安装 Node Snippets插件(编程自带提示) console.log(你好nodejs); //表…

CTF工具下载(1)----随波逐流

为什么要写这个博客喃,因为随波逐流每隔一段时间就会更新,要下载最新版本才能用,但是每次都会有点麻烦,所以写一个博客记录下。 1.进入官网,点击 2.进入城通网盘 3.进入编码工具 4.点击最新版本的随波逐流就下载了&am…

JavaScript进阶6之函数式编程与ES6ESNext规范

函数式编程 柯里化currycurrycompose示例:简化版展开写: debug示例一:示例二: 模板字符串css in js方案 箭头函数问题 生成器 generator应用场景 反射 Reflect 柯里化curry compose是curry的应用 在 lodash/fp underscore ramba …

常用接口测试工具/免费api

一 接口编辑文档 常用的接口文档编写apipost 二 免费接口测试 api 1. thecat 含有: The Cat API - Cat as a Service The Cat API 2. public-apis 进入页面往下拉 三 常用接口测试工具 postman 四 常用接口性能测试工具 Jmeter,loadrunner

GPT演变:从GPT到ChatGPT

Transformer 论文 Attention Is All You Need The dominant sequence transduction models are based on complex recurrent or convolutional neural networks in an encoder-decoder configuration. The best performing models also connect the encoder… https://arxiv.o…

HBuilder X运行项目到微信开发者工具调试和发布Uniapp小程序

1.下载和安装 HBuilderX hbuilder首页:https://www.dcloud.io/hbuilderx.html 下载hbuilder编辑器,选择对应的系统,Windows和mac正式版即可,下载后免安装直接点击即可使用。 打开HBuilder之后,它会要求你注册一个用户,然后才可以使用。 …

广佛站点导航助手小程序产品使用说明书

一、产品简介 广佛站点导航助手小程序是一款专为广佛地区用户设计的地铁导航工具。通过获取用户的实时位置信息,小程序能够迅速定位并展示离用户最近的三个地铁站点。用户可以通过本小程序轻松查找地铁站点,规划出行路线,提高出行效率。 二、…

【Qt 学习笔记】QWidget的toolTip属性 | focusPolicy属性

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ QWidget的toolTip属性 | focusPolicy属性 文章编号:Qt 学习…

Django处理枚举(枚举模型)以及source的使用

Django处理枚举-枚举模型 1、定义模型类、序列化器类2、对上面这些场景使用source参数3、支持连表查询4、自定义序列化输出方法5、案例5 1、定义模型类、序列化器类 定义模型类models.py;项目模型类、接口模型类、用例模型类 from django.db import modelsclass T…

基于Springboot的二手交易平台

基于SpringbootVue的二手交易平台的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录页 首页 商品信息 商品求购 网站公告 留言反馈 个人中心 后台管理 后台首页 用户…

jupyter切换不同的内核(虚拟环境)(anaconda 24.1.2)

jupyter切换不同的内核(anaconda 24.1.2) 主要的两条命令: conda install ipykernel python -m ipykernel install --user --name 环境名称 anaconda的版本号 conda --version实例: 一、首先可以看到已经创…

springboot websocket 持续打印 pod 日志

springboot 整合 websocket 和 连接 k8s 集群的方式参考历史 Java 专栏文章 修改前端页面 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>Java后端WebSocket的Tomcat实现</title><script type"text/javasc…

[Java、Android面试]_18_详解Handler机制 常见handler面试题(非常重要,非常高频!!)

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&#xff0c;每天整理一点&#xff0c;后续会陆续分享出来&#xff0c;感兴趣的朋友可关注收…

ccf201509-3模板生成系统(list,map,字符串综合运用)

问题描述 成成最近在搭建一个网站&#xff0c;其中一些页面的部分内容来自数据库中不同的数据记录&#xff0c;但是页面的基本结构是相同的。例如&#xff0c;对于展示用户信息的页面&#xff0c;当用户为 Tom 时&#xff0c;网页的源代码是&#xff1a; 而当用户为 Jerry 时…