一、快速走进索引页结构
在 InnoDB 存储引擎的架构体系中,数据的存储与管理犹如一座规划精妙、运转有序的城市。在这座数据的城市里,每一块面积为 16KB 的存储区域都被赋予了一个特定的名称 ——“页”(Page)。这些页构成了整个数据存储体系的核心基础设施,其中最为关键的当属 “索引页”(INDEX 页)。索引页承担着存储表中实际记录数据的重要职责,故而也被形象地称作 “数据页”(Data Page)。
(一)整体展示说明
索引页宛如城市里的一栋多层大厦,它不仅肩负着存储数据的重任,还需具备高效的数据检索能力。为达成这一目标,InnoDB 采用了高效的 B+ 树结构,而每个索引页就相当于这棵 B+ 树上的一个节点。
索引页的大小被固定设置为 16KB,这一大小是经过精心优化的。一方面,它能有效利用磁盘空间,避免不必要的空间浪费;另一方面,在内存中对其进行读取操作时也能够快速完成,极大地提升了数据处理的效率。以下为您展示索引页的整体情况:
在这座宛如大厦的索引页里,各个组成部分分工明确、协同运作,全力保障数据实现高效存储与快速访问。其中,File Header 犹如大厦的门卫,严格把控着进出信息,负责对页面的基本信息进行管理;Page Header 则好比楼层管理员,承担着记录页面状态与统计信息的重要职责;Infimum 和 Supremum 恰似大厦的地基与天花板,为整个页面的数据记录划定了边界;User Records 就像是大厦里的居民,是真正存储在页面中的实际数据;Free Space 宛如预留的空房间,为后续新数据的插入预留了存储空间;Page Directory 如同大厦的导航系统,能帮助快速定位到所需的数据记录;File Trailer 则类似安防系统,用于校验页面的完整性,确保数据在存储和传输过程中未出现损坏。
(二)内容说明
File Header(文件头部)
占用空间
文件头部占用 38 字节的存储空间,其中存储着页的一些基础信息,具体如下:
- Page Type(页类型):用于明确标识该页的具体类型,例如数据页或者索引页等。
- Page Number(页号):作为当前页在表空间中的唯一编号,能精准定位该页在整个表空间中的位置。
- Checksum(校验和):主要功能是在页的读写过程中,对其完整性进行检测,防止数据出现损坏或错误。
为了更形象地理解文件头部的作用,我们可以将其类比为办公楼的铭牌。办公楼的铭牌会清晰记录大楼的基本信息以及身份标识,方便人们快速识别和了解大楼的相关情况。同样,文件头部记录的这些基础信息,也能让系统快速识别和管理每一个页。
Page Header(页面头部)
占用空间
页面头部占用 56 字节的存储空间,其中包含了数据页特有的相关信息,具体如下:
- Number of Records(记录数量):该字段记录了当前页中所存储的记录总数,可帮助系统快速了解页面的数据存储规模。
- Free Space Pointer(空闲空间指针):此指针指向页中首个可用的空闲空间位置,便于系统在需要插入新记录时,能迅速定位到可利用的空间。
- Heap Top(堆顶位置):它记录了当前页中数据存储的最高位置,有助于系统清晰掌握页面的数据存储边界。
- Page Level(页级别):用于表示当前页在 B+ 树中所处的层级,这对于数据库进行高效的索引查找和数据检索至关重要。
为了更直观地理解页面头部的作用,我们可以将其类比为大楼的管理办公室。大楼的管理办公室会详细记录楼内的各类管理信息,例如有多少办公室处于空闲状态等。同样,页面头部记录的这些信息,也为数据库系统对数据页的管理和操作提供了关键依据。
Infimum + Supremum(最小记录和最大记录)
占用空间
这两个虚拟记录共占用 26 字节的存储空间,它们的主要作用是明确页中记录的范围,具体如下:
- Infimum Record(最小记录):这是一个具有特殊意义的最小记录,其功能在于标记页的起始位置,为页内记录的排序和查找提供了明确的起点。
- Supremum Record(最大记录):同样是一个特殊的记录,它代表着页内的最大记录,用于标记页的结束位置,有助于系统清晰界定页内记录的边界。
为了更形象地理解这两个虚拟记录的作用,我们可以将它们类比为大楼的基础和屋顶。大楼的基础是整栋建筑的起始支撑点,而屋顶则标志着大楼的最高点和结束边界。与之类似,Infimum Record 和 Supremum Record 分别标示了页的起点和终点,确保了页内记录的有序存储和高效管理。
User Records(用户记录)
占用空间
实际存储的用户数据记录所占用的空间大小并不固定。这些记录包含以下两个关键部分:
- Record Header(记录头部):其中存储着记录的元数据,例如记录的长度以及指向下一条记录的指针。这些元数据对于系统管理和定位记录起着至关重要的作用。
- Record Data(记录数据):这部分是真正的数据内容,涵盖了各个字段的值,是用户数据的核心体现。
为了更形象地理解这些用户数据记录,我们可以将其类比为实际的办公室。在办公室里,员工们正专注地工作,而办公室就如同用户数据记录,里面详细记录着具体的数据内容,是整个数据体系中实际承载信息的地方。
Free Space(空闲空间)
占用空间
空闲空间的占用大小并不固定,它主要用于存储新插入的数据记录。随着记录不断插入到页中,空闲空间会逐渐减少。具体的使用情况如下:
- Insertions(插入操作):当有新的记录需要插入时,数据库系统会在空闲空间区域内寻找合适的位置来存放新记录。
- Deletions(删除操作):若有记录被删除,其所占用的空间会被释放并重新归入空闲区域,以便后续新记录使用。
为了更形象地理解空闲空间的作用,我们可以将其类比为尚未出租的办公室。这些办公室处于闲置状态,等待未来新员工(数据)的入驻,具有很强的灵活性和扩展性。
Page Directory(页面目录)
占用空间
页面目录所占用的空间大小并不固定,它包含了记录的相对位置信息,主要用于实现对记录的快速检索。具体详情如下:
- Directory Slots(目录槽):这些目录槽如同精准的指针,分别指向页中各个记录所在的位置。借助它们,系统能够方便、快捷地定位和检索到目标记录。
- Efficiency(效率优势):页面目录的存在极大地提升了记录检索的效率。通过它,系统无需逐一遍历所有记录,就可以迅速定位到所需记录的位置。
为了更直观地理解页面目录的功能,我们可以将其类比为大楼的导览图。在大楼里,导览图能够帮助人们迅速找到特定的办公室(即数据记录),节省了大量的寻找时间,提高了办事效率。同样,页面目录在数据库中也为快速定位记录提供了便利,大大提升了数据检索的效率。
File Trailer(文件尾部)
占用空间
文件尾部占用 8 字节的存储空间,其中包含了用于验证页完整性的校验信息。具体而言:
- Checksum(校验和):该字段的作用是再次对页的数据完整性进行验证,其目的在于确保数据在读写操作过程中没有受到破坏。无论是在数据写入磁盘时可能出现的错误,还是在从磁盘读取数据时可能产生的干扰,校验和都能通过特定的算法检测出来。
为了更形象地理解文件尾部校验信息的作用,我们可以将其类比为大楼的安保系统。大楼的安保系统时刻监控着大楼的各个方面,确保大楼的安全和完整性不受威胁。同样,文件尾部的校验信息就像数据库页的“安保系统”,守护着页内数据的完整与准确。
二、索引页与记录行的简单关系说明
在 InnoDB 中,数据页通过双向链表连接,每个数据页内的记录行按照主键值从小到大的顺序组成单向链表,并且每个数据页都有一个页目录用于快速定位记录。
查找记录时,先在页目录中使用二分法定位到特定槽,再在该槽对应的记录组中顺序遍历找到目标记录。通过这种设计,InnoDB 能够高效地管理和查找数据,确保数据库系统的高性能和可靠性。
(一)数据页的双向链表结构
在 InnoDB 存储引擎里,每个数据页都被巧妙地组织成一个双向链表。这一结构的独特之处在于,每个数据页都配备了指向前一个页和后一个页的指针,而这些指针以及页的基础信息均记录在 File Header 之中。
借助这种双向链表结构,InnoDB 能够极为便捷地开展数据页的插入、删除以及遍历操作。当需要插入新的数据页时,只需调整相关页的前后指针指向即可;进行删除操作时,同样通过修改指针来移除指定的数据页;在遍历数据页时,也能依据指针依次访问各个数据页。
这样的设计无疑为数据页之间的连接和管理提供了高效的解决方案,确保了数据在不同页之间能够有序流动和存储,提升了整个存储系统的性能和稳定性。
(二)记录行的单向链表结构
在 InnoDB 存储引擎的每个数据页中,记录行依据主键值从小到大的顺序,被精心组织成一个单向链表。这种有序的排列方式极大地提升了在数据页内查找记录的效率。每一条记录不仅承载着自身的业务数据,还持有指向下一条记录的指针,凭借这个指针,系统能够按照顺序依次遍历数据页中的所有记录。
每个数据页都配备了一个页目录,它可以被形象地视为数据页内部的索引结构。页目录会将数据页内的记录划分为多个组,每个组在页目录中都对应一个槽。借助页目录,InnoDB 能够迅速定位到特定记录所在的组,从而显著减少遍历记录所需的时间成本。
当需要通过主键查找某条特定记录时,InnoDB 会首先运用二分法在页目录中快速定位到对应的槽。页目录中的槽明确指向其对应的记录组,随后系统会在该组内顺序遍历记录,直至找到目标记录。这种查找过程巧妙地融合了二分查找和顺序遍历的优势,既保证了查找的高效性,又确保了查找结果的精确性。
三、InnoDB 数据页中的 User Records 与 Free Space
在 InnoDB 数据页里,User Records(用户记录)和 Free Space(空闲空间)这两部分的关系极为紧密。随着新记录持续不断地插入到数据页中,Free Space 部分的空间会逐步被分配给 User Records 部分用于存储新记录,直至 Free Space 被完全耗尽。
当一个数据页被填满后,InnoDB 会主动申请一个新的数据页,并把这个新的数据页链接到现有的双向链表之中,从而继续存储后续的新记录。具体来说,在数据页尚未填满之前,数据的存储操作主要发生在 User Records 和 Free Space 这两个区域;而当数据页填满之后,新记录的存储就会延伸到双向链表中的其他数据页上。
(一)页满前的处理
初始状态
- User Records:初始为空,没有实际数据存储。
- Free Space:占据大部分页空间,等待新记录的插入。
存储过程
- 记录插入:当用户发起插入一条记录的操作时,系统会从 Free Space(空闲空间)部分分配出一块大小合适的区域,专门用于存储这条新记录。随后,这条记录会被完整地存储到 User Records(用户记录)部分。
- 空间调整:随着不断有新记录插入,User Records 部分的空间会逐渐扩大,从而能够容纳越来越多的用户数据。与此同时,Free Space 部分的可用空间会持续减少,逐渐被 User Records 部分所 “蚕食”。
- 页满状态:当 Free Space 部分的空间被全部用完,整个数据页都被 User Records 部分占据时,这就表明该数据页已满,无法再继续存储新的记录了。
(二)页满后的处理
当数据页内的 Free Space(空闲空间)部分被 User Records(用户记录)部分完全占据后,就标志着该数据页已达到饱和状态。此时,InnoDB 存储引擎会自动触发以下一系列操作:
申请新的数据页: 数据库引擎会在表空间里开辟一个新的数据页,为后续新记录的存储提供空间,保证数据存储的连续性。
更新链表指针:新申请的数据页将被无缝接入现有的数据页双向链表中。通过精确更新链表指针,确保各个数据页之间能够保持有序且连贯的连接,维护数据页在链表结构中的逻辑顺序。
维护 B+ 树结构: 若该数据页为索引页,InnoDB 会对 B+ 树结构进行相应的调整与维护。通过插入新的数据页到 B+ 树的合适位置,保证 B+ 树的平衡性和有序性,进而维持索引查询的高效性。