Mysql数据在磁盘上的存储结构

一. 前言

一行数据的存储格式大致如下所示:

变长字段的长度列表,null值列表,数据头,column01的值,column02的值,column0n的值…

二. 变长字段

在MySQL里有一些字段的长度是变长的,是不固定的,比如VARCHAR(255)之类的这种类型的字段,实际上他里面存放的字符串的长度是不固定的,有可能是“hello”这么一个字符串,也可能是“hello word”这么一个字符串。

  • 示例1
格式VARCHAR(10)CHAR(1)CHAR(1)
数据helloaa
存储方式0x05 null值列表 数据头 hello a a
  • 示例2
    多个变长字段, 是逆序存储
格式VARCHAR(10)VARCHAR(5)VARCHAR(20)CHAR(1)CHAR(1)
数据helloa2aa3aa
存储方式0x05 0x02 0x03 null值列表 数据头 hello a a
  • 为什么要逆序存储.
在 MySQL 中,对于变长字段(如 VARCHAR),其长度信息在存储时确实可能以逆序方式存储,这主要涉及到存储格式和性能优化的考量。这个特性尤其在早期版本的 MySQL 中比较明显,而在新版本中,由于存储格式的改进和优化,这种差异可能不那么直观。以下是一些可能导致逆序存储长度信息的原因:

### 1. 存储效率

在某些场景下,将变长字段的长度信息以逆序方式存储可以提高存储效率。例如,如果一个表包含多个变长字段,MySQL 需要在记录的开始处存储这些字段的长度信息。通过逆序存储这些长度信息,MySQL 可以更有效地处理记录中字段值的增减变化,因为这样做可以减少因字段长度变化而导致的数据移动。

### 2. 记录格式

MySQL 中,尤其是 InnoDB 存储引擎,采用了多种记录格式(如 COMPACT 和 REDUNDANT)。在某些记录格式中,字段长度的存储方式可能被设计为逆序,部分原因是为了优化记录的解析过程。在解析一条记录时,从记录的末尾开始可以更快地定位到可变长度字段的实际内容,尤其是在需要跳过某些字段以访问特定字段时。

### 3. 兼容性和历史原因

MySQL 的不同版本和存储引擎在记录格式和存储策略上可能有所不同。一些设计决策,包括字段长度信息的存储方式,可能受到向后兼容性和历史遗留问题的影响。随着 MySQL 版本的发展,存储格式和算法不断优化,但在一些情况下,逆序存储长度信息的方式可能被保留下来,以确保数据的一致性和有效的性能表现。


三.mysql innodb_default_row_format 可以配置那些值, 有什么区别

在MySQL中,innodb_default_row_format选项指定了InnoDB表创建时的默认行格式。这个设置对于新创建的表非常重要,因为它影响了数据的存储方式、空间利用率和性能。innodb_default_row_format可以配置为以下几个值,每个值代表不同的行格式:

可配置的值及其区别

  1. Redundant

    • 这是早期版本的InnoDB行格式,默认使用在MySQL 5.0及更早版本中。
    • 它提供了最基本的特性集合,但在空间利用率和性能方面并不是最优的。
    • Redundant行格式支持较小的最大行大小和较少的数据类型优化。
  2. Compact

    • 从MySQL 5.0版本引入,是一个比Redundant更高效的行格式,旨在改进空间利用率。
    • 它减少了头信息的尺寸,并采用了更高效的方式存储NULL值和可变长度字段。
    • 对于许多应用而言,Compact是一个好的默认选择,因为它提供了较好的空间效率而不牺牲太多性能。
  3. Dynamic

    • 在MySQL 5.7.9及以后版本中,Dynamic成为了默认的行格式。
    • 它解决了Compact格式中一些限制,特别是关于BLOB和TEXT类型字段的更高效存储。在Dynamic格式中,这些类型的字段只在行中存储20字节的指针,实际数据存储在外部页面。
    • Dynamic行格式提供了更好的空间利用率,特别是对于包含大量BLOB或TEXT字段的表。
  4. Compressed

    • Compressed行格式允许对整行数据进行压缩,进一步节省存储空间。
    • 它特别适用于那些磁盘空间成本高昂或者需要存储大量历史数据的环境。
    • 使用Compressed格式可能会对CPU资源产生额外负担,因为需要在读写时进行压缩和解压缩操作。

选择合适的行格式

选择哪种行格式取决于具体的应用需求。DynamicCompressed格式在空间利用率方面提供了显著的优势,特别是对于包含大量长文本或BLOB字段的表。然而,Compressed格式可能会引入一定的性能开销。对于大多数应用,Dynamic行格式提供了一个很好的平衡点,特别是在MySQL 5.7.9及以后版本中,它成为了默认选择。

配置方法

在MySQL中,你可以通过几种方式查询默认的行格式(row format)。默认的行格式是指当你创建一个新表且没有指定行格式时,MySQL所使用的行格式。下面介绍两种常见的方法来查询默认行格式:

    1. 查看全局变量

MySQL允许你通过查询全局系统变量来了解当前的默认行格式。你可以使用以下SQL命令查询默认的行格式:

SHOW VARIABLES LIKE 'innodb_default_row_format';

这条命令会返回innodb_default_row_format变量的值,该值表示InnoDB存储引擎默认使用的行格式。可能的返回值包括RedundantCompactDynamic等。

    1. 查看服务器配置文件

MySQL的默认行格式也可以在服务器的配置文件(通常是my.cnfmy.ini,具体取决于你的操作系统)中进行设置和查看。在配置文件中搜索innodb_default_row_format这一行。例如:

[mysqld]
innodb_default_row_format=dynamic

如果在配置文件中设置了该参数,它将决定默认的行格式。请注意,更改配置文件需要重启MySQL服务器才能生效。

  • 附加信息

  • MySQL版本的影响:不同版本的MySQL可能有不同的默认行格式设置。例如,在MySQL 5.7.9及以后版本中,默认行格式是DYNAMIC

  • 修改默认行格式:你可以通过修改配置文件或设置全局变量的方式来更改默认的行格式,但请注意更改默认行格式可能会影响新创建表的性能和存储效率。

  • 表级行格式设置:即使更改了默认行格式,你仍然可以在创建表时通过ROW_FORMAT选项指定特定表的行格式,这将覆盖全局默认设置。

四. NULL值列表

对所有的NULL值,不通过字符串在磁盘上存储,而是通过二进制的bit位来存储,一行数据里假设有多个字段的值都是NULL,那么这多个字段的NULL,就会以bit位的形式存放在NULL值列表中。

  • 示例
    建表语句
CREATE TABLE customer (
	name VARCHAR(10) NOT NULL,
	address VARCHAR(20),
	gender CHAR(1),
	job VARCHAR(30),
	school VARCHAR(50)
) ROW_FORMAT=COMPACT;

上面那个表就是一个假想出来的客户表,里面有5个字段,分别为name、address、genderjob、school,就代表了客户的姓名、地址、性别、工作以及学校。

其中有4个变长字段,还有一个定长字段,然后第一个name字段是声明了NOT NULL的,就是不能为NULL,其他4个字段都可能是NULL的。

存储数据: “jack NULL m NULL xx_school”

  1. 先看变长字段长度列表
    一共有4个变长字段, 变长字段的值是NULL,就不用在变长字段长度列表里存放他的值长度了. 所以在上面那行数据中,只有name和school两个变长字段是有值的,把他们的长度按照逆序放在变长字段长度列表中就可以了

0x09 0x04 NULL值列表 头信息 column1=value1 column2=value2 … columnN=valueN

  1. NULL值列表
    允许值为NULL,不是说一定值就是NULL了,只要是允许你为NULL的字段,在这里每个字段都有一个二进制bit位的值,如果bit值是1说明是NULL,如果bit值是0说明不是NULL。
    比如上面4个字段都允许为NULL,每个人都会有一个bit位,这一行数据的值是“jack NULL m NULL xx_school”,然后其中2个字段是null,2个字段不是null,所以4个bit位应该是:1010
    NULL值列表存放的时候,他一般是8个bit位的倍数,如果不足8个bit位就高位补0

0x09 0x04 00000101 头信息 column1=value1 column2=value2 … columnN=valueN

五. 数据头 (40个bit)

数据头是用来描述这行数据

这40个bit位里,第一个bit位和第二个bit位,都是预留位,是没任何含义的

一个bit位是delete_mask,他标识的是这行数据是否被删除了

1-23 : delete_mask4: min_rec_mask5-9 : n_owned10-23: heap_no24-26: record_type27-40: next_record
预留位是否被删除在B+树里每一层的非叶子节点里的最小值, 用于指示是否有记录具有相同的键值位于它之后, 用于优化记录的读取在B+树索引结构中,一个索引记录(record)“拥有”的相邻记录数当前这行数据在记录堆里的位置这行数据的类型: 0代表的是普通类型,1代表的是B+树非叶子节点,2代表的是最小值数据,3代表的是最大值数据指向他下一条数据的指针

六. 字符串存储(根据字符集编码存储)

表结构:

CREATE TABLE customer (
	name VARCHAR(10) NOT NULL,
	address VARCHAR(20),
	gender CHAR(1),
	job VARCHAR(30),
	school VARCHAR(50)
) ROW_FORMAT=COMPACT;

存储数据: jack NULL m NULL xx_school

真实存储类似 (非最终存储结构, 字符串尚未编码):
0x09 0x04 00000101 0000000000000000000010000000000000011001 jack m xx_school

字符串根据数据库指定的字符集编码,进行编码之后再存储的

编码后的格式(非最终存储结构):
0x09 0x04 00000101 0000000000000000000010000000000000011001 616161 636320 6262626262

在实际存储一行数据的时候,会在他的真实数据部分,加入一些隐藏字段

  1. 首先有一个DB_ROW_ID字段,这就是一个行的唯一标识,是他数据库内部的一个标识,不是你的主键ID字段。
    如果没有指定主键和unique key唯一索引的时候,他就内部自动加一个ROW_ID作为主键。

  2. 接着是一个DB_TRX_ID字段,这是跟事务相关的,他是说这是哪个事务更新的数据,这是事务ID

  3. 最后是DB_ROLL_PTR字段,这是回滚指针,是用来进行事务回滚的

实际一行数据存储(最终)
0x09 0x04 00000101 0000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)00000000032D(DB_TRX_ID) EA000010078E(DB_ROL_PTR) 616161 636320 6262626262

七. 行溢出

在MySQL的InnoDB存储引擎中,“行溢出”(Row Overflow)是指一行数据过大,无法完全存储在一个数据库页(Page)中时发生的情况。这通常发生在包含大量文本或二进制数据(如BLOB或TEXT类型字段)的行上。InnoDB的页面大小通常为16KB,当一行数据的总大小超过这个限制时,就会发生行溢出。

  • 为什么会有行溢出?
    InnoDB使用B+树存储机制来组织数据表和索引。每个B+树节点(页)有一个最大的空间限制,默认情况下是16KB。大多数行数据都能完整地存储在单个页内,但当遇到特别大的字段值时,如大文本或BLOB字段,整行数据可能无法适应单个页的空间限制。

  • 行溢出的处理机制:
    当InnoDB遇到一个无法适应单个页的大行时,它采用的策略是将主要的行数据保存在原始页中,但会将大字段的一部分或全部移动到其他页(溢出页)上。原始记录页中的大字段位置会被一个指针替代,这个指针指向存储实际数据的溢出页。

  • 行溢出的影响:

性能影响:访问涉及行溢出的数据可能需要额外的磁盘I/O操作,因为需要读取一个或多个额外的溢出页来获取完整的行数据。这种额外的I/O开销可能会导致性能下降,特别是在大量随机访问的场景中。

空间利用:虽然行溢出机制允许InnoDB表存储大于页面大小的行数据,但这种方式可能导致存储空间的利用率不是很高。溢出页可能不会完全填满,特别是当存储非常大的字段时。

  • 如何管理行溢出:

适当的表设计:尽可能避免在表中使用大量的大型字段。如果应用确实需要存储大量文本或二进制数据,考虑将这些数据分割成较小的部分,或者使用外部存储系统。

选择合适的行格式:对于包含大字段的表,使用DYNAMIC或COMPRESSED行格式可能更合适。这些行格式提供了更高效的行溢出数据管理机制。

监控和优化:使用工具和命令(如SHOW TABLE STATUS)来监控表的大小和行格式,以及定期进行数据库优化,可以帮助管理和减轻行溢出的影响。

八. 数据页

MySQL中进行数据操作的最小单位应该是数据页
执行crud的时候,都会从磁盘上加载数据页到Buffer Pool的缓存页里去,然后更新了缓存页后,又会刷新回磁盘上的数据页里去

数据页拆分成了很多个部分,大体上来说包含了文件头、数据页头、最小记录和最大记录、多个数据行、空闲空间、数据页目录、文件尾部。

  • 数据区域存储占比

其中文件头占据了38个字节,
数据页头占据了56个字节,
最大记录和最小记录占据了26个字节,
数据行区域的大小是不固定的,
空闲区域的大小也是不固定的,
数据页目录的大小也是不固定的,
然后文件尾部占据8个字节。

九. 表空间

表都是有对应的表空间的,每个表空间就是对应了磁盘上的数据文件,在表空间里有很多组数据区,一组数据区是256个数据区,每个数据区包含了64个数据页,是1mb

表空间的第一组数据区的第一个数据区的头三个数据页,都是存放特殊信息的;

表空间的其他组数据区的第一个数据区的头两个数据页,也都是存放特殊信息的

在这里插入图片描述

创建的表,其实都是有一个表空间的概念,在磁盘上都会对应着“表名.ibd”这样的一个磁盘数据文件
在物理层面,表空间就是对应一些磁盘上的数据文件。

有的表空间,比如系统表空间可能对应的是多个磁盘文件,有的我们自己创建的表对应的表空间可能就是对应了一个“表名.ibd”数据文件。

然后在表空间的磁盘文件里,会有很多很多的数据页,

一个表空间里包含的数据页实在是太多了,不便于管理,所以在表空间里又引入了一个数据区的概念,英文就是extent

一个数据区对应着连续的64个数据页,每个数据页是16kb,所以一个数据区是1mb,然后256个数据区被划分为了一组。

对于表空间而言,他的第一组数据区的第一个数据区的前3个数据页,都是固定的,里面存放了一些描述性的数据。比如FSP_HDR这个数据页,他里面就存放了表空间和这一组数据区的一些属性。

IBUF_BITMAP数据页,里面存放的是这一组数据页的所有insert buffer的一些信息。

INODE数据页,这里也是存放了一些特殊的信息

然后这个表空间里的其他各组数据区,每一组数据区的第一个数据区的头两个数据页,都是存放特殊信息的,比如XDES数据页就是用来存放这一组数据区的一些相关属性的,其实就是很多描述这组数据区的东西

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可视化-实验五-Pyecharts工具包的使用及文本数据可视化

1.2.1 pyecharts的数据类型以及新的数据导入逻辑 由于pyecharts背后封装的js库,会涉及到数据类型转化。它暂时要求输入数据必须是python的基础数据类型,比如字符串,列表,字典,而不能是序列这样的数据类型。因此序列输入…

RockChip Android13 添加/删除ListPreference方法

概述: 本章将讲述在Android添加或删除ListPreference的几种方法,并以EthernetSettingsActivity为例,添加/删除一项ListPreference: 默认效果图: 添加后效果图: 方法一: 1、全部添加xml 在Activity类中使用addPreferencesFromResource()方法解析XML文件并添加Prefere…

Node.js安装与配置环境 v20.13.1(LTS)

1 下载 Node.js — Run JavaScript Everywhere LTS -- long-term support,长期维护版本 如果要下载其他版本在download里选择下载 2 安装 一路点击next,默认安装路径C:\Program Files\nodejs 3 环境变量配置 1)Path环境变量增加nodejs安装…

艾体宝方案 | 加密USB金融解决方案

在现代金融行业中,保护敏感数据和合规性已成为至关重要的任务。为了帮助金融公司应对移动性风险和合规挑战,我们提供了一种高效的加密USB解决方案。 一、为什么金融公司需要加密USB解决方案 1、降低移动性风险 金融服务公司正在迅速过渡到一种模式&a…

将本地托管模型与 Elastic AI Assistant 结合使用的好处

作者:来自 Elastic James Spiteri, Dhrumil Patel 当今公共部门组织利用生成式人工智能解决安全挑战的一种方式。 凭借其筛选大量数据以发现异常模式的能力,生成式人工智能现在在帮助团队保护其组织免受网络威胁方面发挥着关键作用。 它还可以帮助安全专…

短信平台群发服务有什么优点

短信平台群发服务有什么优点 提高营销效率 短信平台群发服务利用自动化技术,可以帮助企业迅速向大量潜在客户营销信息。相比传统的逐一方式,群发服务可以同时大批目标客户,大大提高了营销效率。企业可以轻松地在短时间内覆盖更多的潜在客户&…

JavaSE——异常(2/2)-异常的处理(记录异常并提示 、尝试重新修复)

目录 记录异常并提示 案例演示 流程解析 写法优化 尝试重新修复 开发中对于异常的常见处理方式 一层一层往上抛出异常,并且在最上层捕获异常,分为两种不同的处理方式。 例如,B站网页报错就是采取的第一种方式: 记录异常并…

linux 性能监控命令之dstat

1. dstat 系统默认为安装,直接安装阿里源后,yum install -y dstat安装即可,该命令整合了 vmstat , iostat 和 ifstat,我们先看下效果: 我们先看看具体参数: [rootk8s-master ~]# dstat --help …

C++STL初阶(1):string的使用及初阶原理

此文作为学习stl的笔记,许多普及、概念性的知识点将不再罗列(如stl的发展、背景等) 便于读者作为复习等方法了解。 0.STL简介(笔记向) STL不是祖师爷本贾尼实现的,是在惠普实验室中实现的。其作为一个数据结…

加密“发射台”:未来通信的新模式

随着区块链技术的飞速发展,加密“发射台”作为一种新兴的安全通信工具,正逐渐受到关注。本文将从专业角度深入探讨加密“发射台”的概念、原理、应用场景及其未来发展趋势,以期为读者提供有深度和逻辑性的思考。 一、加密“发射台”的概念与…

开源项目介绍-02 Aubio【1】环境配置和使用 @ Ubuntu + Pycharm + Python

前言: aubio 是一组算法和工具,用于标记和变换音乐和声音。它扫描或监听音频信号,并尝试识别音乐事件。例如,当鼓被击打时,它能检测到音符的频率,或者一个有节奏的旋律的节拍是多少。 aubio 的功能包括&a…

java 文件表创建及前后端使用

表结构task_file 前端具体到业务表单 <el-form-item label"任务附件" prop"taskAttachment"><el-upload ref"upload" accept".jpg, .png, .txt, .xlsx, .doc, .docx, .xls, .pdf, .zip, .rar":action"upload.url" …

C语言例题39、输入一个正整数,将其反方向逆序输出

#include <stdio.h>void main() {int x;int ge; //个位int result 0;printf("请输入一个正整数&#xff1a;");scanf("%d", &x);while (x > 0) {//解题原理ge x % 10;//每次分解取得个位的数字result result * 10 ge;//个十百千万顺序向左…

限购仅剩6地,透过房价地图看楼市行情!

同一天&#xff0c;两地取消限购&#xff01; 5月9日&#xff0c;继杭州取消限购之后&#xff0c;西安也宣布全面取消住房限购&#xff01; 现在&#xff0c;我们透过几幅楼市数据的分布地图&#xff0c;来看看5月的楼市行情&#xff01; 楼市限购&#xff0c;仅剩6地&#…

YOLOv9改进策略 :一种新颖的通用倒瓶颈(UIB)搜索块助力检测| 轻量化之王MobileNetV4

💡💡💡创新点:轻量化之王MobileNetV4 开源 | Top-1 精度 87%,手机推理速度 3.8ms,原地起飞! 最主要创新:引入了通用倒瓶颈(UIB)搜索块,这是一个统一且灵活的结构,它融合了倒瓶颈(IB)、ConvNext、前馈网络(FFN)以及一种新颖的额外深度可分(ExtraDW)变体技…

【iOS】事件传递与响应机制

文章目录 前言事件UIEvent一、事件传递遍历顺序 二、手势识别三、响应机制UIResponder&#xff08;响应者&#xff09;响应者链 四、相关应用扩大button点击范围穿透事件 总结 前言 提到响应者链与事件传递&#xff0c;如果看过其他人的博客&#xff0c;经常能看到这经典的三张…

《探索信息技术中心一体化系统架构:提升企业数字化转型的效率与能力》

在当今数字化时代&#xff0c;信息技术中心&#xff08;IT Center&#xff09;扮演着至关重要的角色&#xff0c;它不仅是企业的技术支撑&#xff0c;更是推动数字化转型的引擎。为了更好地应对日益复杂的业务需求和技术挑战&#xff0c;许多企业开始探索一体化系统架构&#x…

引用数据类型 栈内存 堆内存

let m { a: 10, b: 20 }; let n m; n.a 15; console.log(m.a) // 15 原因&#xff1a;基本数据类型存储在栈内存中&#xff0c;引用数据类型存储在堆内存中 &#xff0c;引用数据类型存储在堆内存中会在栈内存中创建一个指针&#xff0c;栈内存中的这个指针指向堆内存中的地…

英语学习笔记9——How are you today?

How are you today? 你好吗&#xff1f; 词汇 Vocabulary well adj. 好的 n. 井 fine adj. 美好的 两个方面&#xff1a;天气、身体。 搭配&#xff1a;a fine day 晴朗的一天    It’s a fine day today. 今天很晴朗。 good adj. 好的 口语偏多 搭配&#xff1a;Good jo…

基于光纤技术的新能源汽车电池安全监测--FOM²系统

为什么要进行动力电池包的温度监测&#xff1f; 新能源电动汽车的动力电池包的工作温度&#xff0c;不仅会影响电池包性能&#xff0c;而且直接关系到车辆安全。时有发生的新能源汽车电池包起火事件&#xff0c;对电池包、冷却系统以及电池管理系统&#xff08;BMS&#xff09…
最新文章