# 表
## 索引组织表
innodb存储引擎中,表都是根据主键顺序组织存放的,这种存储方式被称为索引组织表(index organized table)。在innodb存储引擎表中,每张表都有主键(primary key),如果在创建表时没有显式指定主键,那么innodb会按照如下方式创建主键:
- 首先判断表中是否存在非空的唯一索引(unique not null)字段,如果有,则其为主键
- 如果不存在非空唯一索引,那么innodb会自动创建一个6字节大小的指针作为主键
如果有多个非空唯一索引,innodb存储引擎将会选择第一个定义的非空唯一索引作为主键。
## innodb逻辑存储结构
在innodb的存储逻辑结构中,所有的数据都被逻辑存放在表空间(table space)中。表空间则由`段(segement),区(extent),页(page)`组成。
组成如图所示:
### 表空间
表空间为innodb存储引擎逻辑结构的最高层,所有数据都存放于表空间中。innodb存在一个默认的共享表空间`ibdata1`,在开启`innodb_file_per_table`参数后,每张表内的数据可以单独存放到一个表空间。
#### innodb_file_per_table
`innodb_file_per_table`参数启用会导致每张表的`数据、索引、插入缓冲bitmap页`存放到单独的文件中;但是其他数据,例如`回滚(undo)信息,插入缓冲页,系统事务信息,double write buffer`等还是存放在默认的共享表空间中。
### 段(segment)
如上图所示,表空间是由段(segment)所组成的,常见的段分为`数据段,索引段,回滚段`等。
在innodb存储引擎中,数据即索引,索引即数据。`数据段即为B+树的叶子节点(Leaf node segment)`,`索引段即为B+树的非叶子节点(Non-leaf node segment)`。
### 区(Extent)
区是由连续页组成的空间,在任何情况下每个区的大小都为1MB。为了保证区中页的连续性,innodb存储引擎会一次性从磁盘申请4~5个区。在默认情况下,innodb存储引擎中页的大小为`16KB`,一个区中包含64个页。
在新建表时,新建表的大小为96KB,小于一个Extent的大小1MB,因为每个段Segmenet开始时,都会有至多32个页大小的碎片页,等使用完这些页后才会申请64个连续页作为Extent。
都与一些小表或是undo这样的段,可以在开始时申请较少的空间,节省磁盘容量开销。
### 页(Page)
innodb存储引擎中页的大小默认为`16KB`,默认的页大小可以通过`innodb_page_size`参数进行修改。通过该参数,可以将innodb的默认页大小设置为4K,8K。
页是innodb磁盘管理的最小单位,在innodb中,常见的页有:
- 数据页(B-tree node)
- undo页(undo log page)
- 系统页(system page)
- 事务数据页(transaction system page)
- 插入缓冲位图页(insert buffer bitmap)
- 插入缓冲空闲列表页(insert buffer free list)
- 未压缩的二进制大对象页(uncompressed blob page)
- 压缩的二进制大对象页(compressed blob page)
### 行
innodb存储引擎是面向行的,数据按行进行存放。每个页中至多可以存放`16KB/2 - 200`行的记录,即7992行记录。
## innodb行记录格式
innodb存储引擎以行的形式进行存储,可以通过`show table status like '{table_name}'`的语句来查询表的行格式,示例如下:
```sql
show table status like 'demo_t1'
```
| Name | Engine | Version | Row\_format | Rows | Avg\_row\_length | Data\_length | Max\_data\_length | Index\_length | Data\_free | Auto\_increment | Create\_time | Update\_time | Check\_time | Collation | Checksum | Create\_options | Comment |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| demo\_t1 | InnoDB | 10 | Dynamic | 0 | 0 | 16384 | 0 | 32768 | 0 | 1 | 2025-01-30 15:18:57 | null | null | utf8mb4\_0900\_ai\_ci | null | | |
上述示例中表的row_format为dynamic。
### Compact
在使用Compact行记录格式时,一个页中存放数据越多,其性能越高。
Compact格式下行记录的存储格式如下:
| 变长字段长度列表 | NULL标志位 | 记录头信息 | 列1数据 | 列2数据 | ...... |