Mysql存储结构

154 阅读4分钟

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后,如何存储?

  1. 内联存储 (Inline Storage)

    默认情况下,InnoDB 会尝试将数据尽可能存储在主记录所在的页中。 如果行中的某些列(如大字段)导致数据量超过页大小,InnoDB 会将一部分数据存储在溢出页中。 主记录所在的页仍然会存储字段的元信息(如列长度)和溢出页的指针。

  2. 溢出页 (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)。