从数据页的角度理解B+树查询

数据库中的存储结构

记录是按照行来存储的,但是数据库的读取并不以行为单位,否则一次读取(也就是一次 I/O 操作)只能处理一行数据,效率会非常低。

因此在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载。也就是说,数据库管理存储空间的基本单位是页。

一个页中可以存储多个行记录,同时在数据库中,还存在着区(Extent)、段(Segment)和表空间(Tablespace)。

一个表空间包括了一个或多个段,一个段包括了一个或多个区,一个区包括了多个页,而一个页中可以有多行记录。

区:(多个区组成一张表)

区是比页大一级的存储结构,在 InnoDB 存储引擎中,一个区会分配 64 个连续的页(连续空间)。因为 InnoDB 中的页大小默认是 16KB,所以一个区的大小是 64*16KB=1MB。

段:(相当于表,多个段组成一个库)

段由一个或多个区组成,区在文件系统是一个连续分配的空间(在 InnoDB 中是连续的 64 个页),不过在段中不要求区与区之间是相邻的。段是数据库中的分配单位,不同类型的数据库对象以不同的段形式存在。当我们创建数据表、索引的时候,就会相应创建对应的段,比如创建一张表时会创建一个表段,创建一个索引时会创建一个索引段。

 表空间:(逻辑容器)

表空间是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有一个或多个段,但是一个段只能属于一个表空间。数据库由一个或多个表空间组成,表空间从管理上可以划分为系统表空间、用户表空间、撤销表空间、临时表空间等。

在 InnoDB 中存在两种表空间的类型:共享表空间和独立表空间。如果是共享表空间就意味着多张表共用一个表空间。如果是独立表空间,就意味着每张表有一个独立的表空间,也就是数据和索引信息都会保存在自己的表空间中。独立的表空间可以在不同的数据库之间进行迁移。

 

 数据页内的结构

 页按类型划分的话,常见的有数据页(保存 B+ 树节点)、系统页、Undo 页和事务数据页等。

表页的大小限定了表行的最大长度,不同 DBMS 的表页大小不同。

页内的七个部分

数据库 I/O 操作的最小单位是页,与数据库相关的内容都会存储在页结构里。数据页包括七个部分,分别是

文件头(File Header) :描述页的信息

在文件头中有两个字段,分别是 FIL_PAGE_PREV 和 FIL_PAGE_NEXT,它们的作用相当于指针,分别指向上一个数据页和下一个数据页。连接起来的页相当于一个双向的链表。

页头(Page Header) : 页的状态信息

最大最小记录(Infimum+supremum)

两个虚拟的行记录(不管插入了什么数据,页中的最小记录 和 最大记录 都是页生成时候的这两条伪记录。)

用户记录(User Records) 实际存储的行记录内容

最小和最大记录”和“用户记录”属于行记录,存放页内的主要数据,占较大一部分空间。

空闲空间(Free Space)页中尚未使用的空间

空闲空间是个灵活的部分,当有新的记录插入时,会从空闲空间中进行分配用于存储新记录

页目录(Page Directory)页中的记录相对位置

它起到了记录的索引作用,因为在页中,记录是以单向链表的形式进行存储的。单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索,因此在页目录中提供了二分查找的方式,用来提高记录的检索效率。

文件尾(File Tailer)结尾信息

文件尾的校验方式采用 Hash 算法进行校验。当进行页传输的时候,如果突然断电了,造成了该页传输的不完整,这时通过文件尾的校验和(checksum 值)与文件头的校验和做比对,如果两个值不相等则证明页的传输有问题,需要重新进行传输,否则认为页的传输已经完成。

7个部分可以按照功能分为3个部分

首先是文件通用部分:也就是文件头和文件尾。它们类似集装箱,将页的内容进行封装,通过文件头和文件尾校验的方式来确保页的传输是完整的。

第二部分是记录部分:页的主要作用是存储记录,所以“最小和最大记录”和“用户记录”部分占了页结构的主要空间。另外空闲空间是个灵活的部分,当有新的记录插入时,会从空闲空间中进行分配用于存储新记录。

第三部分是索引部分:这部分重点指的是页目录,它起到了记录的索引作用,因为在页中,记录是以单向链表的形式进行存储的。单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索,因此在页目录中提供了二分查找的方式,用来提高记录的检索效率。

 

 用页结构对比 B+ 树

在一棵 B+ 树中,每个节点都是一个页,每次新建节点的时候,就会申请一个页空间。

同一层上的节点之间,通过页的结构构成一个双向的链表(页文件中的两个指针字段)。

非叶子节点,包括了多个索引行,每个索引行里存储索引键和指向下一层页面的页面指针。

最后是叶子节点,它存储了关键字和行记录,在节点内部(也就是页结构的内部)记录之间是一个单向的链表,但是对记录进行查找,则可以通过页目录采用二分查找的方式来进行。

B+树的检索路径

如果通过 B+ 树的索引查询行记录,首先是从 B+ 树的根开始,逐层检索,直到找到叶子节点,也就是找到对应的数据页为止,将数据页加载到内存中,页目录中的槽(slot)采用二分查找的方式先找到一个粗略的记录分组,然后再在分组中通过链表遍历的方式查找记录。

普通索引和唯一索引在查询效率上有什么不同?

唯一索引就是在普通索引上增加了约束性,使关键字唯一,找到了关键字就停止检索。

而普通索引,可能会存在用户记录中的关键字相同的情况,根据页结构的原理,当我们读取一条记录的时候,不是单独将这条记录从磁盘中读出去,而是将这个记录所在的页加载到内存中进行读取。

InnoDB 存储引擎的页大小为 16KB,在一个页中可能存储着上千个记录,因此在普通索引的字段上进行查找也就是在内存中多几次“判断下一条记录”的操作,对于 CPU 来说,这些操作所消耗的时间是可以忽略不计的。所以对一个索引字段进行检索,采用普通索引还是唯一索引在检索效率上基本上没有差别。(NOT NULL 影响索引效率)。


同一棵树上同一层的页与页之间采用双向链表,而在页里面,记录之间采用的单向链表的方式。

链表这种数据结构的特点是增加、删除比较方便,所以在对记录进行删除的时候,有时候并不是真的删除了记录,而只是逻辑上的删除,也就是在标记为上标记为“已删除”。

但链表还有个问题就是查找效率低,因此在页结构中还专门设计了页目录这个模块,专门给记录做一个目录,通过二分查找法的方式进行检索提升效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL B树是一种多路搜索树,用于在数据库中快速地索引和检索数据。它是一种平衡树,每个非叶子节点最多包含m个子节点,其中m为阶数。具体回答如下: MySQL B树的特点有以下几点: 1. 多路搜索树:B树的非叶子节点可以拥有多个子节点,这样可以大幅减少层数,提高搜索效率。 2. 平衡树:B树的每个节点从根节点到叶子节点的路径长度相等,这样可以保持树的平衡,避免出现极端情况导致搜索效率下降。 3. 顺序存储:B树的节点通过顺序存储在磁盘上,这样可以提高IO效率,减少磁盘读写次数。 4. 自平衡:插入或删除一个节点后,B树会通过旋转、分裂或合并等操作重新平衡,保持树的平衡性。 5. 提供快速的索引和检索:通过B树,可以快速地定位到所需数据的位置,减少了遍历的时间。 对于MySQL面试题中关于B树的问题,可能会有以下几种考察角度: 1. 数据库索引:B树数据库中广泛应用于索引的实现,可以通过B树迅速地定位到所需数据的位置。 2. 插入和删除操作:B树的自平衡特性使得插入和删除操作的时间复杂度为O(logn),保证了高效的修改操作。 3. 阶数的选择:阶数m的选择会影响B树的节点个数和树的高度,进而影响查询效率和内存占用,需要根据实际应用场景进行合理选择。 4. B+树和B-树:MySQL中还存在B+树和B-树等变种,可以对其进行介绍和比较。 总结来说,MySQL B树是一种用于数据库索引的多路搜索平衡树,通过自平衡、顺序存储等特性,提供快速的索引和检索功能。理解B树的原理和应用场景对于数据库快速查询和修改操作非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值