B树和B+树的区别

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

B树与B+树均属于多路平衡查找树,是数据库索引、文件系统等核心场景中常用的数据结构,其核心设计目标为优化磁盘I/O效率,减少磁盘访问次数。二者在结构设计、数据存储、查询逻辑等核心层面存在显著差异,下文将从关键维度展开详细对比,明确其各自的适用场景与核心优势。

🌳 结构可视化

B树结构

        [10, 20, 30]         ← 内部节点存储数据和键
         /    |    \
        /     |     \
    [5,8]  [15,18]  [25,28,35]
    数据     数据      数据     ← 所有节点都存储实际数据

B+树结构

        [10, 20, 30]         ← 内部节点只存储键(索引)
         /    |    \
        /     |     \
    [10]    [20]    [30]     ← 内部节点继续
     |       |       |
[5,8,10]→[15,18,20]→[25,28,30]→[35,40]  ← 叶子节点存储数据并链表连接
 数据     数据      数据      数据

一、核心结构区别

1. B树结构

B树是一种平衡多路查找树,对于阶为m(即单个节点最多可存储的关键字数量)的B树,除叶子节点与根节点外,其余每个节点的子节点个数需满足「⌈m/2⌉ ≤ 子节点数 ≤ m」的约束条件。

  • 每个节点同步存储关键字及对应的数据记录(或数据指针),所有关键字按升序规则排列,确保查询的有序性。
  • 叶子节点与非叶子节点(分支节点)结构保持一致,均包含关键字与对应数据,且各叶子节点之间无直接关联关系,独立存在。
  • 当树的高度不小于2时,根节点至少包含2个子节点;所有叶子节点处于同一层级,以此保障树的平衡性,确保查询效率的稳定性。

2. B+树结构

B+树是B树的优化迭代版本,同样遵循多路平衡查找树的核心规则,阶数定义与B树保持一致,其结构设计更侧重于提升查询效率与数据有序性,适配大数据量场景的访问需求。

  • 分支节点仅存储关键字及对应的子节点指针,不存储具体数据记录,所有数据均集中存储于叶子节点,实现索引与数据的分离。
  • 所有叶子节点按关键字升序排列,且通过指针形成有序链表结构,可快速定位范围查询的边界,大幅提升范围查询效率。
  • 叶子节点包含树中全部关键字,分支节点中的关键字均为叶子节点关键字的索引映射,即每个分支节点的关键字对应其下一级子节点中的最大(或最小)关键字,用于引导查询方向。

二、核心功能与特性区别

数据存储位置

分支节点与叶子节点均存储数据及关键字

仅叶子节点存储数据,分支节点仅存储索引关键字及指针

查询效率

查询效率具有不确定性:若目标数据存在于分支节点,可直接返回结果,无需访问叶子节点;若目标数据仅存在于叶子节点,则需遍历至树的最底层,平均磁盘I/O次数相对较多。

查询效率稳定:无论目标数据所处位置,均需遍历至叶子节点,平均磁盘I/O次数固定(等于树的高度),适配高频查询场景,稳定性更优。

范围查询

效率较低:需逐一遍历多个分支节点与叶子节点,因叶子节点无有序链表关联,无法快速定位范围查询的边界,查询耗时较长。

效率较高:叶子节点有序且通过指针形成链表,定位到范围查询的起始节点后,可通过链表快速遍历所有符合条件的节点,大幅降低查询耗时。

关键字冗余

无冗余:每个关键字在树中仅出现一次,无重复存储,节省存储空间。

有冗余:分支节点的关键字均在叶子节点中重复出现,通过冗余设计提升索引定位效率,保障查询性能。

插入/删除操作

操作复杂度较高:插入、删除操作可能导致分支节点的数据发生变动,需频繁执行节点分裂、合并操作以维护树的平衡性,运维成本较高。

操作复杂度较低:插入、删除操作主要在叶子节点执行,分支节点仅需调整索引映射关系,节点分裂、合并的频率显著降低,维护成本更优。

磁盘I/O效率

效率较低:分支节点需存储数据,导致单个节点可承载的关键字数量减少,树的高度相对较高,磁盘访问次数较多,I/O效率受限。

效率较高:分支节点仅存储索引信息,单个节点可承载更多关键字,树的高度显著降低(通常比B树矮1-2层),大幅减少磁盘I/O次数,提升数据访问效率。

三、适用场景区别

1. B树适用场景

B树适用于以随机查询为主、范围查询需求较少的场景,且对数据访问的实时性要求较低,典型应用场景包括:

  • 小型数据库索引场景:数据量较小,磁盘I/O压力较低,无需复杂的范围查询支持;
  • 早期文件系统目录索引:如EXT3文件系统,适配小规模文件存储的目录查询需求;
  • 低频次数据修改场景:需快速定位单个数据,且数据插入、删除操作频次较低,无需频繁维护树结构。

2. B+树适用场景

B+树适用于范围查询频繁、随机查询需求较多的场景,尤其适配大数据量存储场景,是目前主流数据库索引的首选数据结构,典型应用场景包括:

  • 关系型数据库索引:MySQL、Oracle等主流关系型数据库的聚簇索引、非聚簇索引均基于B+树实现,适配高频查询与范围查询需求;
  • 大数据量文件系统索引:如EXT4、XFS等现代文件系统,可高效支撑大规模文件的索引与查询;
  • 高频范围查询场景:需频繁执行分页查询、区间统计等操作,B+树的有序链表结构可显著提升此类场景的查询效率。

四、核心总结

B树与B+树的核心差异源于数据存储位置的设计差异及叶子节点的结构设计:B树的设计侧重单次查询的极限效率,但其查询稳定性及范围查询效率相对不足;B+树通过“索引与数据分离”及“叶子节点有序链表”的设计,实现了更稳定的查询效率、更高的磁盘I/O利用率及更高效的范围查询能力,更适配现代数据库、大数据量存储的应用需求。

综上可知:随机查询需求为主、数据量较小的场景优先选用B树;范围查询频繁、大数据量的场景优先选用B+树,这也是B+树成为主流数据库索引结构的核心原因。

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

MySQL存储引擎与索引 文章被收录于专栏

还在纠结MySQL存储引擎怎么选?选错直接拉垮系统性能!MySQL插件式存储引擎架构适配多元业务:InnoDB(默认)支持事务、行级锁,扛高并发OLTP场景;MyISAM查询快无事务,适配读多写少场景;Memory读写极速但无持久化,适合临时缓存;Archive高压缩归档日志,CSV便捷跨系统交互,NDB支撑分布式集群。本期专栏拆解各引擎核心特性与选型逻辑,教你选对引擎,让数据库性能拉满!

全部评论
如果大家在工作学习中或者面试中遇到不会的问题可以将问题发在评论区,如果是经典的问题,我可以给出对应的文章,欢迎大家讨论
点赞 回复 分享
发布于 03-10 14:18 北京

相关推荐

前30min自我介绍+项目经历。ps:项目经历感觉没问很深的细节,也没拷打,就看我简历的技术栈来问的(看你这边写熟练mysql,那巴拉巴拉,看你熟练http,tcp,那巴拉巴拉)。agent项目细节一个没问。项目部分问题:1.你这些是实习项目吗?(我说找的然后自己做优化)2.你这个里面为什么用Lua脚本?3.redis那个服务端,怎么保证这个原子性的?4.redis的实现架构上,比如说他的线程模型,进程模型,以及他的并发角度,来解释一下他的原子性。5.redis的持久化策略?为什么两个都用?6.我看你用了一个令牌桶+滑动窗口双算法限流,这个地方能简单描述一下调研了哪些限流方案?,或者你了解哪些限流的方案,以及他们的优缺点,以及在你这个场景最终为什么选择了这个方式?7.你怎么测试方案的性能,讲一下你当时部署的架构和测试的方法。8.你是本地部署还是?那还用redis做限流吗?有没有更好的办法呀?9.你部署的是什么模式呀,比如多个进程还是多个线程?或者单个进程,还是说协程怎么样的。10.你项目中遇到的最大困难是什么,怎么解决的。7-9答的不是很好,一直在想架构要怎么回答。八股文:1.mysql索引结构是什么?(前面架构给我问懵了,这一块没想到,然后就一直掰扯mysql的类型和优化)2.OSI七层模型,简单。场景题:客户端和服务端tcp连接后,长时间没有传数据,服务端突然宕机了,此时客户端和服务端还是连接的吗?(没懂装懂解释了一下三次握手和四次握手)编程题:单链表倒数第k个节点,只运行一次遍历。(秒了)反问环节:1.问个人表现怎么样,说我的项目理解不够深2.扯了一下ai coding ,然后我也讲了一下我使用aicoding的经验。感觉很慌,面前最担心的是编程题,没想到面后最担心的却是回答问题。问了hr小姐姐说两天内收到结果,唉更多干货资料:*****************************************
查看14道真题和解析
点赞 评论 收藏
分享
04-13 22:27
门头沟学院 Java
一、 实习相关二、 MySQL 数据库原理5. 除了 LIKE 这种模糊查询,还有什么情况会导致 MySQL 索引失效?6. MySQL 的索引有哪些类型?7. 要查看一个 SQL 的执行性能应该怎么看?8. MySQL 的表数据量达到什么量级之后性能可能会急剧下降?为什么?9. SQL 里面的 UNION 和 UNION ALL 有什么区别?三、 个人项目与 Redis 核心原理10. 你的项目里面用 Redis 做了什么?11. 为什么用 Redis 做缓存?(为什么 Redis 执行得这么快?)12. 为什么 Redis 单线程能有那么高的并发量?除了主线程,Redis 还有其他子线程吗?13. Redis 单机的 QPS 一般能达到多少?14. 简单介绍一下 Redis 的 IO 多路复用是一个什么样的机制?15. Redis 里面常见的基础数据结构和高级数据结构有哪些?16. 为什么要用 Lua 脚本?17. Redis 里的 TTL 是个什么概念?四、 分布式架构基础18. 分布式的概念是什么?为什么在分布式场景下单机的 JVM 锁解决不了一人一单的问题?19. 微服务架构和分布式架构有什么不一样?20. 单体架构和分布式架构各自有什么优劣?五、 Java 基础与 JVM 原理21. 什么是 Java 的双亲委派机制?22. 为什么要用双亲委派机制?(如果不使用会导致什么样的安全问题?)23. 你了解哪些垃圾回收算法?24. JVM 里面年轻代和老年代一般的垃圾回收机制是怎样的?(分代回收思想)25. 怎么识别哪些对象是需要回收的垃圾?26. 列举几个常见的 GC Roots。六、 并发编程 (JUC)27. 线程池常用的几个核心参数是什么?28. 核心线程数和最大线程数在任务执行机制上有什么区别?(请描述任务提交到线程池后的流转过程)七、 线上排查与网络协议29. 如果某天发现线上的服务突然卡死了,大概有什么样的分析和排查方式?30. 如果让你人为制造一个 OOM(内存溢出),你要怎么去写代码?31. Java 里面的 Error 和 Exception 有什么区别?32. 如果有用户反馈网站很慢,大概的一个排查和分析路径是怎样的?33. 从在浏览器中输入 URL 打开网页到返回结果,中间经历了哪些步骤?八、 算法手写题34. 两个有序数组的中位数。
查看30道真题和解析
点赞 评论 收藏
分享
评论
1
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务