Files
rikako-note/mysql/mysql文档/mysql_表.md
2025-02-02 19:57:30 +08:00

9.9 KiB
Raw Blame History

索引组织表

innodb存储引擎中表都是根据主键顺序组织存放的这种存储方式被称为索引组织表index organized table。在innodb存储引擎表中每张表都有主键primary key如果在创建表时没有显式指定主键那么innodb会按照如下方式创建主键

  • 首先判断表中是否存在非空的唯一索引unique not null字段如果有则其为主键
  • 如果不存在非空唯一索引那么innodb会自动创建一个6字节大小的指针作为主键

如果有多个非空唯一索引innodb存储引擎将会选择第一个定义的非空唯一索引作为主键。

innodb逻辑存储结构

在innodb的存储逻辑结构中所有的数据都被逻辑存放在表空间table space中。表空间则由segementextentpage组成。

组成如图所示:

表空间

表空间为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的默认页大小设置为4K8K。

页是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}'的语句来查询表的行格式,示例如下:

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数据 ......

变长字段长度列表

Compact行记录格式其首部是一个非Null变长字段长度列表,其按照列的顺序逆序放置,变长列的长度为:

  • 如果列的长度小于255字节用1字节表示
  • 如果列的长度大于255字节用2个字节表示

变长字段的长度不能小于2字节因为varchar类型最长长度限制为65535。

NULL标志位

NULL标志位为bitmap代表每一列是否为空。如果行中存在n个字段可为空那么NULL标志位部分的长度为ceiling(n/8)。

记录头信息

record header固定占用5字节其中record header的各bit含义如下所示

名称 大小(bit)
() 1 未知
() 1 未知
deleted_flag 1 该行是否已经被删除
min_rec_flag 1 该行是否为预订被定义的最小记录行
n_owned 4 该记录拥有的记录数
heap_no 13 索引堆中该条记录的排序记录
record_type 3 记录类型000代表普通001代表B+树节点指针, 010代表infimum011代表supremum1xx保留
next_record 16 页中下一条记录相对位置

除了上述3个部分之外其他部分就是各个列的实际值。

在Compact格式中NULL除了占有NULL标志位外不占用任何实际空间。

每行数据中,除了有用户自定义的列外,还存在两个隐藏列,即事务id列回滚指针列长度分别为6字节和7字节。

如果innodb表没有自定义主键每行还会增加一个rowid列。

行溢出数据

innodb存储引擎可能将一条记录中某些数据存储在真正的存储数据页面之外。一般来说blob、lob这类大对象的存储位于数据页面之外。

当行数据的大小特别大导致一个页无法存放2条行数据时innodb会自动将占用空间大的blob字段或varchar字段值放到额外的uncompressed blob page中。

dynamic

dynamic格式几乎和compact格式相同但是对于每个blob字段其存储只消耗20字节用于存储指针。

而对于Compact格式其会在blob格式中存储768字节的前缀字节。

char存储结构

char(n)字段中n代表字符长度而非字节长度故而在不同字符集下char类型字段的内部存储可能不是定长的。

例如在utf8字符集下ab我们两个字符串其字符数都是2个但是ab其占用2字节我们占用4字节即使同样是char(2)类型的字符串,其占用字节数量仍然有可能不同。

innodb数据页结构

innodb中页是磁盘管理的最小结构页类型为B-tree Node的页存放的即是表中行的实际数据。

innodb数据页由如下7个部分组成

  • File Header文件头
  • Page Header页头
  • Infimum和Supremum Records
  • user records用户记录即行记录
  • free space空闲空间
  • page directory页目录
  • file trailer文件结尾信息

file headerpage headerfile trailer的大小是固定的分别为38568字节这些空间用于标记页的一些信息例如checksum数据页所在B+树的层数等。

image.png

File Header

File Header用于记录页的一些头信息由8个部分组成共占38字节

名称 大小 说明
FIL_PAGE_SPACE_OR_CHKSUM 4 代表页的checksum值
FIL_PAGE_OFFSET 4 表空间中页的偏移位置
FIL_PAGE_PREV 4 当前页的上一个页B+树决定叶子节点为双向列表
FIL_PAGE_NEXT 4 当前页的下一个页
FIL_PAGE_LSN 8 代表该页最后被修改的日志序列位置LSN
FIL_PAGE_TYPE 2 存储引擎页类型
FIL_PAGE_FILE_FLUSH_LSN 8 该值仅在系统表空间的一个页中定义代表文件至少被更新到了该LSN值对于独立的表空间该值为0
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 4 代表页属于哪个表空间

Infimum和Supremum record

在innodb存储引擎中每个数据页都有两行虚拟的行记录用于限定记录边界。Infimum是比该页中所有主键值都要小的值Supremum是比任何可能值都要大的值。这两个值在页创建时被建立,并且在任何情况下都不会被删除。

user record 和 free space

user reocrd代表实际存储行记录中的内容free space则是代表空闲空间同样是链表数据结构在一条记录被删除后该空间会被加入到空闲列表中。

page directory

page directory页目录中存放了记录的相对位置这些记录指针被称为目录槽directory slotsinnodb中槽是一个稀疏目录一个槽中可能包含多个记录记录Infimum的n_owned总为1记录Supremum的n_owned取值范围为[1,8]其他用户记录的n_owned为[4,8]。当记录被插入或删除时,需要对槽进行分裂或平衡的维护操作。

在slots中记录按照索引键值顺序存放可以通过二叉查询迅速找到记录的指针。

由于在innodb存储引擎中page directory是稀疏目录二叉查找结果只是一个粗略的结果