Mysql存储结构
- 数据表:表空间是 MySQL 中最顶层的存储逻辑单位。它是用来存放数据文件的,所有的数据库对象(如表、索引等)都存储在表空间中。
- 区:表空间由多个区(Extent)组成,是 InnoDB 管理存储的基本分配单元。大小:每个区固定为 1MB,一个区包含 64 个页。当需要存储新数据时,InnoDB 会按区分配存储空间,以减少频繁分配空间的开销。
- 页:页是存储引擎中最小的物理存储单位。大小:默认页大小为 16KB(可配置为 4KB、8KB 或 64KB)。数据页:存储表的行记录。
- 行:行是 MySQL 中数据的最小逻辑存储单位。每个行记录存储在数据页中。
- 段:段是区的集合,专门用于管理特定类型的数据(例如表数据或索引数据)。段用于组织并管理多个区。
- 空间层次结构:表空间(Tablespace) -> 包含 区(Extent) -> 由多个 页(Page) 组成 -> 页中存储 行(Row)
如果一行数据大小为1k,那么10G数据大概多少行?多少去?多少页?
一个区默认为1m, 默认64页, 1页16k。
那么, 1页16k,一行1k的话,1页数据是16行。64页为1m,1024个1m就是1g,也就是1024个区为1g。
所以,10G数据, 为10240个区, 10240 * 64个页, 10240 * 64 * 16个行 = 10,485,760(大约1千万行)
假设建立一张表
CREATE TABLE example (
id INT PRIMARY KEY,
name VARCHAR(100)
);
其存储步骤
- 分配段:创建表时,InnoDB 会为表数据分配一个数据段,为主键索引分配一个索引段。
- 分配区:数据段从表空间中分配一个或多个区(每个区大小为 1MB)。
- 分配页:每个区被分割为 64 个页(每页大小为 16KB)。
- 存储行:每行数据会存储到页中,页是具体存放行数据的地方。 所有的变更都必须先更新缓冲池中的数据,然后缓冲池中的脏页会以一定的频率被刷入磁盘(flush)
行记录超过16k后,如何存储?
-
内联存储 (Inline Storage)
默认情况下,InnoDB 会尝试将数据尽可能存储在主记录所在的页中。 如果行中的某些列(如大字段)导致数据量超过页大小,InnoDB 会将一部分数据存储在溢出页中。 主记录所在的页仍然会存储字段的元信息(如列长度)和溢出页的指针。
-
溢出页 (Overflow Page)
如果行数据无法完全放入主记录页,InnoDB 会创建一个或多个溢出页存储超出的部分数据。 主记录页中会存储溢出页的引用(类似指针),以便关联超出部分的数据。
普通字段(如 VARCHAR)的存储主要受页大小限制,超出时可能溢出到额外页中。 大字段(BLOB/TEXT) 会部分存储在主记录页,剩余数据存储在溢出页中。(根据ROW_FORMAT来决定)
InnoDB 支持以下几种行格式(row_format)?
- COMPACT: 默认的存储格式,存储效率较高,行数据紧凑存储。 对于 BLOB 和 TEXT 类型字段,存储前 768 字节在主记录页中,剩余数据存储在溢出页。
- REDUNDANT: 最早的行存储格式,为了向后兼容保留,一般不推荐使用,通常只在迁移旧系统时需要。
- DYNAMIC: 大字段使用外部存储(Off-Page Storage),优化了 BLOB 和 TEXT 类型存储。 大字段(如 BLOB/TEXT 类型)尽可能存储在外部页(溢出页)中,仅存储元信息和必要部分在主记录页。
- COMPRESSED: 行数据会进行压缩存储,节省磁盘空间,但对 CPU 有一定开销。 读取时需要解压,写入时需要压缩,因此会增加一定的 CPU 开销。
- DEFAULT: MySQL 根据存储引擎的默认值自动选择行格式(通常是 COMPACT 或 DYNAMIC)。