目录

mysql innodb记录结构

innodb记录结构

我们知道读写磁盘的速度非常慢,和内存读写差了几个数量级,所以当我们想从表中获取某些记录时,InnoDB存储引擎需要一条一条的把记录 从磁盘上读出来么?

不,那样会慢死,InnoDB采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁 盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。

InnoDB行格式

我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式。设计InnoDB存储引擎的大叔们到现在为止设计了4种不同类型的行格式,分别 是Compact、Redundant、Dynamic和Compressed行格式。

我们可以在创建或修改表的语句中指定行格式: CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称 ALTER TABLE 表名 ROW_FORMAT=行格式名称

行溢出数据现象

MySQL对一条记录占用的最大存储空间是有限制的,除了BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字 节。所以MySQL服务器建议我们把存储类型改为TEXT或者BLOB的类型。

MySQL中磁盘和内存交互的基本单位是页,也就是说MySQL是以页为基本单位来管理存储空间的, 我们的记录都会被分配到某个页中存储。而一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M)类型的列就最多可以存储65532个字节,这样就可能造成一个页存放不了一条记录的尴尬情况。

在Compact和Reduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些 页的地址。

行溢出的临界点

那发生行溢出的临界点是什么呢?也就是说在列存储多少字节的数据时就会发生行溢出? MySQL中规定一个页中至少存放两行记录,只要知道如果我们想一个行中存储了很大的数据时,可能发 生行溢出的现象。

页结构

一个InnoDB数据页的存储空间大致被划分成了7个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的: pic1.png

不论我们怎么对页中的记录做增删改操作,InnoDB始终会维护一条记录的单链表,链表中的各个节点是按照主键值由小到大的顺序连接起来的。

主键值为2的记录被我们删掉了,但是存储空间却没有回收,如果我们再次把这条记录插入到表中,InnoDB并没有因为新记录的插入而为它申请新的存储空间,而是直接复用了原来被删除记录的存储空间

》每个数据页的File Header部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表。

数据页中的目录

主键值由小到大顺序串联成一个单链表,我们想根据主键值查找页中的某条记录需要遍历,有了目录就效率提高了。

在一个数据页中查找指定主键值的记录的过程分为两步:

  1. 通过二分法确定该记录所在的槽,并找到该槽中主键值最小的那条记录。
  2. 通过记录的next_record属性遍历该槽所在的组中的各个记录