mysql查漏补缺笔记3

1. InnoDB、行格式

InnoDB是Mysql默认的存储引擎,由于磁盘本身的读写速度很慢,InnoDB将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是说,通常情况下,InnoDB一次最少从磁盘中读取16KB数据到内存中,一次最少从内存中写16KB数据到磁盘上。

在InnoDB中,数据存储在硬盘上的格式被称为“行格式”或“记录格式”,InnoDB拥有四种不同的“行格式”。

  • COMPACT

直接看图:

image.png

什么是变长字段长度列表?

一些数据类型可以用来指定变长字符(即表示一个字符需要的字节数不确定,比如在utf8字符集中),比如varchar、text等,我们需要将该数据真实占用的字节长度记录下来(注意,变长字段长度列表存储的是字节长度,而不是字节本身)并将各变长字段长度以逆序排列。

什么是NULL值列表?

将值为NULL的列统一管理起来,存储到NULL值列表中。如何记录呢?将每个可以为NULL值的列对应一个二进制位,若该位置为1,则代表相应的列值为NULL。

NULL值列表必须为整数个字节,若不足一个字节,则在高位补0。比如一张表只有三个字段,那么NULL值列表也必须要有一个字节(8个二进制位),其中前5位为0,后3位记录字段的值是否为NULL。

什么是记录头信息?

记录头信息包含了一些当前记录的信息,占用5个字节。具体有哪些信息?如下:

delete_mask:标记是否已经被删除。是的,即使一条数据被删除,这里很可能只是逻辑删除,它在物理上也可以依然可以留存在页中。这些被删除的记录之所以不立即从磁盘上移除,是因为移除它们之后把其他的记录在磁盘上重新排列需要性能消耗,所以只是打一个删除标记而已,所有被删除掉的记录都会组成一个所谓的垃圾链表,在这个链表中的记录占用的空间称之为所谓的可重用空间,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。

min_rec_mask:B+树的每层非叶子节点中的最小记录都会添加该标记。

n_owned:

heap_no:表示当前记录在页中的位置。

record_type:表示当前记录的类型。0表示普通记录,1表示B+树非叶节点记录,2表示最小记录,3表示最大记录。

next_record:表示从当前记录的真实数据下一条记录的真实数据的地址偏移量。(注意这里指向的是真实数据的开头,不是完整数据,完整数据包含真实数据和额外信息)

隐藏列?

除了我们存储的数据外,Mysql还会默认添加一些列,被称为隐藏列,隐藏列包含:行ID、事务ID、回滚指针。

有同学可能有疑问?每行数据不是有自定义的主键作为行ID吗?为什么隐藏列还要生成?InnoDB的主键策略是:优先使用自定义主键,若未自定义,则选用一个Unique键作为主键,若Unique键也未设置,这才使用隐藏列中的行ID。

其余三种行格式有:Redundant、Dynamic、Compressed。不再一一细看了,需要用到时可以再针对性查资料。

2. 页

上面提到了“页”这个概念,它是管理内存和磁盘之间数据的基本单位。它的组成部分如图所示:

image.png

每插入一条记录,InnoDB将会从Free Space申请一块空间交付给User Records使用,存储我们的数据。如果Free Space用完,那么将要申请一块新的页。

3. 页目录

每条记录行在User Records中是以链表形式,以主键为顺序排列的,那如果我要查找其中主键为n的一条记录呢?

最笨的办法就是遍历,但这种方法一旦面对大量的数据无疑效率低下。为了解决这个问题,InnoDB设计了页目录。具体是如何设计的呢?如下:

首先,将所有的记录分成若干个组;每个组的最后一条记录的头信息中的n_owned属性表示该组拥有多少条记录;将每个组最后一条记录的地址偏移量(主要目的是为了计算个数)提取出来,这些偏移量被称为“槽”(slot),存储在页的尾部,这个地方就是页目录(Page Diretory)。

从逻辑上简单来说,就是将所有记录分组,然后将每组的偏移量与个数存入页目录,每组的记录个数一般在1-8之间。

所以在插入数据时,首先通过主键找到合适的槽,该槽对应的n_owned值加一,一旦大于8,则分裂为两个槽。

如果要查找主键为n的记录,先通过二分法找到相应的槽,然后再遍历这个槽。

你可能感兴趣的:(mysql查漏补缺笔记3)