InnoDB 是如何存储数据的?

113 阅读4分钟

image.png

MySQL 把数据存储和查询操作抽象成了存储引擎,不同的存储引擎,对数据的存储和读取方式各不相同。

MySQL 支持多种存储引擎,并且可以以表为粒度设置存储引擎。

因为支持事务,我们最常使用的是 InnoDB。

虽然数据保存在磁盘中,但其处理是在内存中进行的。为了减少磁盘随机读取次数,InnoDB 采用页而不是行的粒度来保存数据,即数据被分成若干页,以页为单位保存在磁盘中

InnoDB 的页大小,一般是 16KB。

各个数据页组成一个双向链表,每个数据页中的记录按照主键顺序组成单向链表;

每一个数据页中有一个页目录,方便按照主键查询记录。

页目录通过槽把记录分成不同的小组,每个小组有若干条记录。

如图中所示,

记录中最前面的小方块中的数字,代表的是当前分组的记录条数,最小和最大的槽指向 2 个特殊的伪记录。

有了槽之后,我们按照主键搜索页中记录时,就可以采用 二分法快速搜索,无需从最小记录开始遍历整个页中的记录链表。

例行总结

InnoDB 使用页(Page)作为磁盘读写的最小单位,默认每个页为16KB。这可以减少磁盘IO次数,提高效率

数据保存在页中,多个页通过双向链表进行链接,方便进行前后页面的读取。

每个页内,记录会按主键排好序,并以单向链表组织。方便进行主键的搜索。

为加速主键查找,InnoDB在每个页中还维护了一个称为**“页目录”的B+树结构**。它会将一个页中的记录分成几个槽(Slot),每个槽包含若干条记录。

通过页目录的B+树,可以快速定位到页内的某个槽,然后再在槽内进行精确查找。

举例子

如果要搜索主键(PK)=15 的记录:

  • 先二分得出槽中间位是 (0+6)/2=3,看到其指向的记录是 12<15,所以需要从 #3 槽后继续搜索记录;
  • 再使用二分搜索出 #3 槽和 #6 槽的中间位是 (3+6)/2=4.5 取整 4,#4 槽对应的记录是 16>15,所以记录一定在 #4 槽中;
  • 再从 #3 槽指向的 12 号记录开始向下搜索 3 次,定位到 15 号记录。

InnoDB使用页来组织存储,并在页内使用B+树索引和链表结构,可以有效提高主键查找的效率,这是MySQL高性能的重要原因之一。

补充

B+树(B+ tree)是一种在计算机科学中广泛用于实现关系型数据库中的索引结构。它是一种自平衡树,用于存储和管理大量数据,通常用于数据库管理系统中以加快数据检索操作的速度。

B+树是一种树状数据结构,通常用于数据库索引。在B+树中,数据按照键值存储在叶子节点上,而中间节点用于加速查找。

B+树的结构示例:

               40
             /    \
         20       60
        /  \     /   \
     10   30  50   70

在这个示例中,我们有一个B+树,树中包含了四个节点。每个节点有两部分:上部是键值,下部是指向子节点或数据的指针。

  • 最上面的节点包含键值40,它有两个子节点:20和60。
  • 节点20有两个子节点:10和30。
  • 节点60有两个子节点:50和70。
  • 叶子节点(最底部)包含实际的数据,例如学生记录等。这些叶子节点是有序的。

B+树的工作原理:

假设我们要查找键值为50的数据。查找过程如下:

  1. 从根节点开始,40不等于50,所以我们移动到右子节点60。
  2. 在节点60中,我们发现50等于50,所以我们找到了匹配的数据,即键值为50的数据。

B+树的关键之一是,无论有多少数据,查找操作的时间复杂度都大致相同。这使得B+树成为数据库索引的理想选择,因为它可以高效地管理和检索大量数据。

学习:Java 核心技术面试精讲学习笔记