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的数据。查找过程如下:
- 从根节点开始,40不等于50,所以我们移动到右子节点60。
- 在节点60中,我们发现50等于50,所以我们找到了匹配的数据,即键值为50的数据。
B+树的关键之一是,无论有多少数据,查找操作的时间复杂度都大致相同。这使得B+树成为数据库索引的理想选择,因为它可以高效地管理和检索大量数据。
学习:Java 核心技术面试精讲学习笔记