MySQL的存储结构分为5级:表空间、段、簇、页、行。
1.表空间 TableSpace
表空间可以看做是 InnoDB 存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。分为:系统表空间、独占表空间、通用表空间、临时表空间、Undo表空间。
由于篇幅原因,把对这几个表空间的介绍放到下一篇文章…
2.段 Segment
表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等,段是一个逻辑的概念。一个ibd文件(独立表空间文件)里面会由很多个段组成。
创建一个索引会创建两个段,一个是索引段:leaf node segment,一个是数据段:non-leafnodesegment。索引段管理非叶子节点的数据。数据段管理叶子节点的数据。也就是说,一个表的段数,就是索引的个数乘以2。
3.簇 Extent
一个段(Segment)又由很多的簇(也可以叫区)组成,每个区的大小是1MB(64个连续的页)。每一个段至少会有一个簇,一个段所管理的空间大小是无限的,可以一直扩展下去,但是扩展的最小单位就是簇。
4.页 Page(重点)
为了高效管理物理空间,对簇进一步细分,就得到了页。簇是由连续的页(Page)组成的空间,一个簇中有64个连续的页。 (1MB/16KB=64)。这些页面在物理上和逻辑上都是连续的。
跟大多数数据库一样,InnoDB也有页的概念(也可以称为块),每个页默认16KB。页是InnoDB存储引擎磁盘管理的最小单位,通过innodb_page_size设置。一个表空间最多拥有2^32个页,默认情况下一个页的大小为16KB,也就是说一个
表空间最多存储64TB的数据。
注意,文件系统中,也有页的概念。操作系统和内存打交道,最小的单位是页Page。文件系统的内存页通常是4K。
SHOW VARIABLES LIKE 'innodb_page_size';
假设一行数据大小是1K,那么一个数据页可以放16行这样的数据。下面的示例就用每页放3行数据:
由于索引属于二叉查找树,所以索引字段是有序的。往表中插入数据时
- 如果一个页面已经写完,产生一个新的叶页面(如果一个簇的所有的页面都被用完,会从当前页面所在段新分配一个簇)
- 如果数据不是连续的,往已经写满的页中插入数据,会导致叶页面分裂
5.行 Row
InnoDB 存储引擎是面向行的(row-oriented),也就是说数据的存放按行进行存放。
文件格式 | 行格式 | 描述 |
---|---|---|
Antelope(Innodb-base) | ROW_FORMAT=COMPACT ROW_FORMAT=REDUNDANT | Compact 和 redumdant 的区别在就是在于首部的存 存内容区别。 compact的存储格式为首部为一个非NULL的变长字段长度列表 redundant 的存储格式为首部是一个字段长度偏移 列表(每个字段占用的字节长度及其相应的位移)。 在 Antelope 中对于变长字段,低于 768 字节的,不 会进行 overflowpage 存储,某些情况下会减少结果集 IO. |
Barracuda(Innodb-plugin) | ROW_FORMAT=DYNAMIC ROW_FORMAT=COMPRESSED | 这两者主要是功能上的区别功能上的。 另外在行里的变长字段和 Antelope 的区别是只存 20 个字节, 其它的 overflowpage 存储。 另外这两都需要开启 innodb_file_per_table=1 |
innodb_file_format 在配置文件中指定;
show variables like "%innodb_file_format%";
SET GLOBAL innodb_file_format=Barracuda;
row_format则在创建数据表时指定
CREATE TABLE tf1
(c1 INT PRIMARY KEY)
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8;
查看行格式(注:需要在命令行操作):
SHOW TABLE STATUS LIKE 'tf1'\G;