MySQL为什么选择B+树作为索引结构?(详解)

在MySQL中,无论是Innodb还是MyIsam,都使用了B+树作索引结构(这里不考虑hash等其他索引)。本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明MySQL为什么选择B+树作为索引结构。

MySQL为什么选择B+树作为索引结构?(详解)

一、二叉查找树(bst):不平衡

二叉查找树(BST,Binary Search Tree),也叫二叉排序树,在二叉树的基础上需要满足:任意节点的左子树上所有节点值不大于根节点的值,任意节点的右子树上所有节点值不小于根节点的值。如下是一颗BST(图片来源)。

MySQL为什么选择B+树作为索引结构?(详解)

当需要快速查找时,将数据存储在BST是一种常见的选择,因为此时查询时间取决于树高,平均时间复杂度是O(lgn)。然而,BST可能长歪而变得不平衡,如下图所示(图片来源),此时BST退化为链表,时间复杂度退化为O(n)。

为了解决这个问题,引入了平衡二叉树。

MySQL为什么选择B+树作为索引结构?(详解)

二、平衡二叉树(AVL):旋转耗时

AVL树是严格的平衡二叉树,所有节点的左右子树高度差不能超过1;AVL树查找、插入和删除在平均和最坏情况下都是O(lgn)。

AVL实现平衡的关键在于旋转操作:插入和删除可能破坏二叉树的平衡,此时需要通过一次或多次树旋转来重新平衡这个树。当插入数据时,最多只需要1次旋转(单旋转或双旋转);但是当删除数据时,会导致树失衡,AVL需要维护从被删除节点到根节点这条路径上所有节点的平衡,旋转的量级为O(lgn)。

由于旋转的耗时,AVL树在删除数据时效率很低;在删除操作较多时,维护平衡所需的代价可能高于其带来的好处,因此AVL实际使用并不广泛。

三、红黑树:树太高

与AVL树相比,红黑树并不追求严格的平衡,而是大致的平衡:只是确保从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。从实现来看,红黑树最大的特点是每个节点都属于两种颜色(红色或黑色)之一,且节点颜色的划分需要满足特定的规则(具体规则略)。红黑树示例如下(图片来源):

MySQL为什么选择B+树作为索引结构?(详解) 

与AVL树相比,红黑树的查询效率会有所下降,这是因为树的平衡性变差,高度更高。但红黑树的删除效率大大提高了,因为红黑树同时引入了颜色,当插入或删除数据时,只需要进行O(1)次数的旋转以及变色就能保证基本的平衡,不需要像AVL树进行O(lgn)次数的旋转。总的来说,红黑树的统计性能高于AVL。

因此,在实际应用中,AVL树的使用相对较少,而红黑树的使用非常广泛。例如,Java中的TreeMap使用红黑树存储排序键值对;Java8中的HashMap使用链表+红黑树解决哈希冲突问题(当冲突节点较少时,使用链表,当冲突节点较多时,使用红黑树)。

对于数据在内存中的情况(如上述的TreeMap和HashMap),红黑树的表现是非常优异的。但是对于数据在磁盘等辅助存储设备中的情况(如MySQL等数据库),红黑树并不擅长,因为红黑树长得还是太高了。当数据在磁盘中时,磁盘IO会成为最大的性能瓶颈,设计的目标应该是尽量减少IO次数;而树的高度越高,增删改查所需要的IO次数也越多,会严重影响性能。

四、B树:为磁盘而生

B树也称B-树(其中-不是减号),是为磁盘等辅存设备设计的多路平衡查找树,与二叉树相比,B树的每个非叶节点可以有多个子树。因此,当总节点数量相同时,B树的高度远远小于AVL树和红黑树(B树是一颗“矮胖子”),磁盘IO次数大大减少。

定义B树最重要的概念是阶数(Order),对于一颗m阶B树,需要满足以下条件:

每个节点最多包含 m 个子节点。如果根节点包含子节点,则至少包含 2 个子节点;除根节点外,每个非叶节点至少包含 m/2 个子节点。拥有 k 个子节点的非叶节点将包含 k – 1 条记录。所有叶节点都在同一层中。

可以看出,B树的定义,主要是对非叶结点的子节点数量和记录数量的限制。

下图是一个3阶B树的例子(图片来源):

 MySQL为什么选择B+树作为索引结构?(详解)

B树的优势除了树高小,还有对访问局部性原理的利用。所谓局部性原理,是指当一个数据被使用时,其附近的数据有较大概率在短时间内被使用。B树将键相近的数据存储在同一个节点,当访问其中某个数据时,数据库会将该整个节点读到缓存中;当它临近的数据紧接着被访问时,可以直接在缓存中读取,无需进行磁盘IO;换句话说,B树的缓存命中率更高。

Revid AI Revid AI

AI短视频生成平台

Revid AI 96 查看详情 Revid AI

B树在数据库中有一些应用,如mongodb的索引使用了B树结构。但是在很多数据库应用中,使用了是B树的变种B+树。

五、B+树

B+树也是多路平衡查找树,其与B树的区别主要在于:

B树中每个节点(包括叶节点和非叶节点)都存储真实的数据,B+树中只有叶子节点存储真实的数据,非叶节点只存储键。在MySQL中,这里所说的真实数据,可能是行的全部数据(如Innodb的聚簇索引),也可能只是行的主键(如Innodb的辅助索引),或者是行所在的地址(如MyIsam的非聚簇索引)。B树中一条记录只会出现一次,不会重复出现,而B+树的键则可能重复重现——一定会在叶节点出现,也可能在非叶节点重复出现。B+树的叶节点之间通过双向链表链接。B树中的非叶节点,记录数比子节点个数少1;而B+树中记录数与子节点个数相同。

由此,B+树与B树相比,有以下优势:

更少的IO次数:B+树的非叶节点只包含键,而不包含真实数据,因此每个节点存储的记录个数比B数多很多(即阶m更大),因此B+树的高度更低,访问时所需要的IO次数更少。此外,由于每个节点存储的记录数更多,所以对访问局部性原理的利用更好,缓存命中率更高。更适于范围查询:在B树中进行范围查询时,首先找到要查找的下限,然后对B树进行中序遍历,直到找到查找的上限;而B+树的范围查询,只需要对链表进行遍历即可。更稳定的查询效率:B树的查询时间复杂度在1到树高之间(分别对应记录在根节点和叶节点),而B+树的查询复杂度则稳定为树高,因为所有数据都在叶节点。

B+树也存在劣势:由于键会重复出现,因此会占用更多的空间。但是与带来的性能优势相比,空间劣势往往可以接受,因此B+树的在数据库中的使用比B树更加广泛。

六、感受B+树的威力

前面说到,B树/B+树与红黑树等二叉树相比,最大的优势在于树高更小。实际上,对于Innodb的B+索引来说,树的高度一般在2-4层。下面来进行一些具体的估算。

树的高度是由阶数决定的,阶数越大树越矮;而阶数的大小又取决于每个节点可以存储多少条记录。Innodb中每个节点使用一个页(page),页的大小为16KB,其中元数据只占大约128字节左右(包括文件管理头信息、页面头信息等等),大多数空间都用来存储数据。

对于非叶节点,记录只包含索引的键和指向下一层节点的指针。假设每个非叶节点页面存储1000条记录,则每条记录大约占用16字节;当索引是整型或较短的字符串时,这个假设是合理的。延伸一下,我们经常听到建议说索引列长度不应过大,原因就在这里:索引列太长,每个节点包含的记录数太少,会导致树太高,索引的效果会大打折扣,而且索引还会浪费更多的空间。

对于叶节点,记录包含了索引的键和值(值可能是行的主键、一行完整数据等,具体见前文),数据量更大。这里假设每个叶节点页面存储100条记录(实际上,当索引为聚簇索引时,这个数字可能不足100;当索引为辅助索引时,这个数字可能远大于100;可以根据实际情况进行估算)。

对于一颗3层B+树,第一层(根节点)有1个页面,可以存储1000条记录;第二层有1000个页面,可以存储1000*1000条记录;第三层(叶节点)有1000*1000个页面,每个页面可以存储100条记录,因此可以存储1000*1000*100条记录,即1亿条。而对于二叉树,存储1亿条记录则需要26层左右。

七、总结

最后,总结一下各种树解决的问题以及面临的新问题:

1)、二叉查找树(BST):解决了排序的基本问题,但是由于无法保证平衡,可能退化为链表;

2)、平衡二叉树(AVL):通过旋转解决了平衡的问题,但是旋转操作效率太低;

3)、红黑树:通过舍弃严格的平衡和引入红黑节点,解决了AVL旋转效率过低的问题,但是在磁盘等场景下,树仍然太高,IO次数太多;

4)、B树:通过将二叉树改为多路平衡查找树,解决了树过高的问题;

5)、B+树:在B树的基础上,将非叶节点改造为不存储数据的纯索引节点,进一步降低了树的高度;此外将叶节点使用指针连接成链表,范围查询更加高效。

推荐学习:MySQL教程

以上就是MySQL为什么选择B+树作为索引结构?(详解)的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1036502.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
在Java中如何使用TreeSet实现有序集合_TreeSet集合操作技巧
上一篇 2025年12月2日 04:01:21
win1升级win11安装方法? win10如何获得win11更新?
下一篇 2025年12月2日 04:01:26

相关推荐

  • 网页空间受限时,如何巧妙实现下拉菜单折叠效果?

    巧妙解决网页空间受限:下拉菜单折叠效果 网页设计中,特别是菜单或选项列表,经常会遇到空间不足的问题。当菜单项过多超出容器宽度时,需要有效机制避免内容溢出,保持布局整洁。本文将介绍一种优雅的解决方案:在空间受限时,将超出部分折叠到下拉菜单中。 此方案的核心在于动态判断元素宽度,根据容器宽度决定哪些菜单…

    2026年9月3日
    000
  • 如何高效管理Magento 2模块:以wolfautoparts.com/product为例

    在为wolfautoparts.com维护其magento 2商店时,我面临的一个主要问题是如何高效地安装和升级其自定义模块wolfautoparts.com/product。每次更新或安装新模块时,都需要确保不影响网站的正常运行,同时还要处理与其他系统的集成问题。 在尝试了多种方法后,我发现使用C…

    用户投稿 2026年9月3日
    100
  • mysql的分页查询语句是什么

    mysql的分页查询语句是:1、“select*from tablename limit index,pageNum”语句;2、“select*from tablename limit  pageNum offset index”语句。 本教程操作环境:windows10系统、mysql8.0.22…

    2026年9月3日
    100
  • mysql中exists的用法是什么

    在mysql中,exists用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回true或false,语法为“SELECT 字段 FROM table WHERE EXISTS (subquery);”。 本教程操作环境:windows10系统、mysql8.0.22版本、…

    2026年9月3日
    000
  • 三爱思获初芯基金投资,系国内半导体晶圆载具领军企业

    ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 初芯基金近日宣布独家投资三爱思半导体材料(苏州)有限公司(简称“三爱思”),推动先进半导体技术落地中国。此轮融资将用于三爱思的产品开发、技术升级、生产优化和团队建设,进一步提升其为国内客户提供高…

    2026年9月3日
    000
  • 电脑主机电源供应不足故障排查及电源更换建议

    电脑主机电源供应不足故障排查及电源更换建议电脑主机电源供应不足故障排查及电源更换建议电脑主机电源供应不足故障排查及电源更换建议电脑主机电源供应不足故障排查及电源更换建议

    电脑电源供电不足会导致系统不稳定甚至无法开机,解决方法包括排查症状、简化负载、软件检查、交叉测试和更换合适电源。首先观察高负载时是否黑屏、重启或外设异常;其次检查电源线、插座、风扇和灰尘情况;再拔掉非必要设备测试;接着用事件查看器和更新驱动辅助判断;有条件可用备用电源交叉测试;计算硬件总功耗并增加2…

    2026年9月3日 用户投稿
    000
  • @Transactional注解下,查询操作会加锁吗?

    @Transactional注解与数据库查询加锁机制 使用@Transactional注解时,数据库查询操作是否加锁取决于数据库的隔离级别。本文将深入探讨这一问题。 场景描述 当多个事务同时对同一张表执行多个查询操作(不涉及增删改)时,数据库是否会进行加锁? 结论分析 答案取决于数据库的隔离级别设置…

    2026年9月3日
    000
  • 有效管理角色与权限:使用litepie/roles解决权限管理难题

    在开发一个多用户系统时,我遇到了一个常见但复杂的问题:如何有效地管理用户角色和权限。最初,我尝试使用自定义的解决方案,但发现管理起来非常繁琐,容易出错,导致系统的安全性和可维护性大打折扣。经过一番研究,我找到了litepie/roles这个强大的角色和权限管理库,它大大简化了我的工作,使得整个系统的…

    用户投稿 2026年9月3日
    000
  • mysql怎样修改注释

    mysql怎样修改注释mysql怎样修改注释mysql怎样修改注释mysql怎样修改注释

    方法:1、利用“alter table 表名 comment ‘修改后的注释’;”语句修改表的注释;2、利用“alter table 表名 modify 字段名 column comment 类型 ‘修改后的注释’;”语句修改字段的注释。 本教程操作环…

    2026年9月3日 用户投稿
    300
  • 飞飞重逢飞行器全攻略:激活驾驶与极速翱翔指南

    飞飞重逢飞行器全攻略:激活驾驶与极速翱翔指南飞飞重逢飞行器全攻略:激活驾驶与极速翱翔指南飞飞重逢飞行器全攻略:激活驾驶与极速翱翔指南飞飞重逢飞行器全攻略:激活驾驶与极速翱翔指南

    你是否向往挣脱地面的桎梏,在云端自由穿梭?《飞飞重逢》的飞行器系统正是你通往天际的通行证!解锁机翼、掌控操纵杆,这份详尽指南将助你成为真正的天空霸主: 机甲觉醒:三步启动你的专属战机碎片收集 — 星空猎人的寻宝征程 深入副本挑战、参与限时活动或完成阵营任务,获取对应飞行器的独特碎片。每架飞行器都拥有…

    2026年9月3日 用户投稿
    100
  • JavaScript原型链中__proto__和[[Prototype]]究竟有何区别?

    深入探究JavaScript原型链中的__proto__和[[Prototype]] 学习JavaScript原型和原型链时,fn.__proto__.__proto__为何等于Fn.prototype而非null,常令人困惑。本文将深入解析__proto__和[[Prototype]]的差异,揭示…

    2026年9月3日
    100
  • win10怎么修改系统默认字体_win10修改系统默认字体方法

    通过修改注册表可更改Windows 10默认字体,首先在Fonts和FontSubstitutes路径下将Segoe UI替换为指定字体名称,如微软雅黑,再重启生效。 如果您希望个性化Windows 10的视觉效果,可以通过修改系统默认字体来实现界面显示的变化。这将影响任务栏、窗口标题栏及其他使用系…

    2026年9月3日
    100
  • SpreadJSx AI 深度融合:从智能函数到数据决策新范式

    SpreadJSx AI 深度融合:从智能函数到数据决策新范式SpreadJSx AI 深度融合:从智能函数到数据决策新范式SpreadJSx AI 深度融合:从智能函数到数据决策新范式SpreadJSx AI 深度融合:从智能函数到数据决策新范式

    当电子表格与大模型相遇,数据处理的边界正被彻底重塑。 在数字化转型的大潮中,电子表格作为企业最基础的数据载体,长期面临操作繁琐、分析门槛高等问题。传统函数公式的记忆负担、数据透视表的配置复杂度、跨语言协作的障碍……这些看似微小的摩擦,日积月累却严重拖慢了企业的效率。 2025年6月,纯前端表格控件S…

    2026年9月3日 用户投稿
    200
  • mysql中with as的用法是什么

    在mysql中,“with as”也叫子查询,用于定义一个sql片段,且该片段会被整个sql语句反复使用很多次,这个sql片段就相当于是一个公用临时表,语法为“with tmp as (查询语句)”。 本教程操作环境:windows10系统、mysql8.0.22版本、Dell G3电脑。 mysq…

    2026年9月3日
    200
  • ICLR 2025 | Diffusion Planner: 基于扩散模型的自动驾驶规划算法,nuPlan SOTA!

    清华大学联合多家机构在iclr 2025发表的最新研究成果《diffusion-based planning for autonomous driving with flexible guidance》提出了一种创新的自动驾驶规划方法——diffusion planner。该方法基于diffusio…

    2026年9月3日
    100
  • AI代理平台选型与实施:五大关键步骤助你成功落地

    ai代理构建平台正以前所未有的速度发展,选择合适的平台对企业至关重要。本文将为您提供一些建议,助您和团队以及供应商共同实现创新。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 如今,CIO和IT团队正从评估独立的AI软件包转向集成自定义AI…

    2026年9月2日
    100
  • Java异步任务编排:如何高效处理多个依赖型第三方接口调用?

    Java异步任务编排:优化多接口调用效率 在高并发环境下,高效处理多个依赖型第三方接口调用至关重要。本文以一个需要调用四个第三方接口的场景为例,探讨如何利用Java的CompletableFuture实现异步任务编排,并优化执行效率。每个接口调用耗时约1.5秒。 场景需求 接口调用需满足依赖关系:接…

    2026年9月2日
    100
  • MySQL导入导出数据结构一致性_Sublime辅助管理跨系统数据迁移模板

    MySQL导入导出数据结构一致性_Sublime辅助管理跨系统数据迁移模板MySQL导入导出数据结构一致性_Sublime辅助管理跨系统数据迁移模板MySQL导入导出数据结构一致性_Sublime辅助管理跨系统数据迁移模板MySQL导入导出数据结构一致性_Sublime辅助管理跨系统数据迁移模板

    跨系统mysql迁移中,sublime text通过文本编辑功能辅助schema管理,确保数据结构一致性。1. 使用mysqldump导出纯净schema并手动清理冗余信息;2. 用sublime text维护结构模板,利用多光标、正则替换、代码片段等功能提升编辑效率;3. 借助项目管理和diff插…

    2026年9月2日 用户投稿
    100
  • mysql怎样修改字段属性

    mysql怎样修改字段属性mysql怎样修改字段属性mysql怎样修改字段属性mysql怎样修改字段属性

    在mysql中,可以利用alter命令修改字段属性,该命令用于修改数据表名或者修改数据表字段,语法为“alter table 表名 modify COLUMN 字段名 新数据类型”。 本教程操作环境:windows10系统、mysql8.0.22版本、Dell G3电脑。 mysql怎样修改字段属性…

    2026年9月2日 用户投稿
    300
  • mysql数据库的查询语句是什么

    mysql数据库的查询语句是什么mysql数据库的查询语句是什么mysql数据库的查询语句是什么mysql数据库的查询语句是什么

    查询语句:1、“select * from 表名;”,可查询表中全部数据;2、“select 字段名 from 表名;”,可查询表中指定字段的数据;3、“select distinct 字段名 from 表名”,可对表中数据进行去重查询。 本教程操作环境:windows7系统、mysql8版本、De…

    2026年9月2日 用户投稿
    200

发表回复

登录后才能评论
关注微信