十年大厂员工终明白:MySQL性能优化的尽头,是对B+树的极致理解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 存储引擎是数据库的核心组件,负责数据的存储与管理。常见存储引擎如MySQL的InnoDB采用B+树结构,以优化读取性能,支持高效查询、范围检索和有序遍历。相比哈希表和B树,B+树通过减少I/O次数,提升大规模数据下的查询效率。本文深入解析B+树的原理、优势及其在MySQL中的应用。

存储引擎
存储引擎是数据库管理系统(DBMS)或键值存储系统的核心组件,它定义了数据在持久化存储介质上如何组织、存储、检索和管理。不同的存储引擎针对特定负载(如读密集型、写密集型、混合型)和数据模型(如关系型、键值型、文档型)进行优化。
目前常见的存储引擎使用的存储数据结构有如下几种。
1)哈希表(Hash Table):提供O(1)平均时间复杂度的单点查询(精确键匹配)。非常适合键值(Key-Value)存储,但天然不支持范围查询或有序遍历(除非对整个数据集扫描)。
2)B+树(Balance+ Tree):为磁盘I/O优化的多路平衡搜索树。广泛用于关系型数据库(如MySQL InnoDB, PostgreSQL)的索引和数据存储。支持高效的单点查询、范围查询和有序遍历。对读密集型和混合型负载友好。
3)LSM树(Log-Structured Merge Tree):专为高写入吞吐量设计的结构。通过将随机写转换为内存中的有序写入和磁盘上的顺序批量写入来优化写性能。广泛应用于写密集型的NoSQL数据库(如Google Bigtable, Apache HBase, Cassandra, RocksDB, LevelDB)。

MySQL B+树

image.png

MySQL的存储引擎,主要分InnoDB和MyISAM。InnoDB是MySQL的默认引擎,InnoDB使用B+树存储数据。表中的数据(主键索引)和辅助索引最终都会使用 B+ 树来存储,其中前者会以 的方式存储,而后者会以 的方式进行存储。

image.png

为了分析 InnoDB 选择 B+ 树作为其索引结构的原因,可以将其与 B 树和哈希表进行对比。随着互联网的快速发展,数据存储规模已攀升至千万甚至亿级,而典型的互联网应用场景往往是读多写少。例如,热点新闻的访问、商品列表的展示以及基于价格、地理位置等条件的智能化推荐排序,都需要高效的数据查询和排序能力。因此,数据存储结构需要满足以下核心需求。
1)高效的查询性能:尤其是在范围查询和排序操作上,需要具备优异的性能表现。
2)充分利用顺序 I/O 和 Page Cache 机制:通过优化 I/O 性能,减少磁盘访问的延迟。
3)支持大规模数据存储:在保证高效查询的同时,尽可能减少写入操作的 I/O 开销。

image.png

由于哈希映射关系,哈希表在查找单条数据时候,能保证O(1)的时间复杂读。但哈希表在范围查询和排序遍历时候,只能进行全表扫描并依次判断是否满足条件。全表扫描对数据库的性能影响非常大。比如如下的SQL语句:

SELECT * FROM commodity WHERE price > 10 AND price < 100
SELECT * FROM commodity WHERE ORDER BY price DESC

平均时间复杂度比O(1)稍慢的是O(logn),这类数据结构有平衡二叉树(AVL Tree),红黑树(RB Tree)、B树(B Tree)、B+树(B+ Tree)等。他们天然就支持排序、范围查找操作。

image.png

平衡二叉树在一般情况下查询性能非常好,但平衡二叉树单个节点只能保存一个数据,因此当覆盖大量数据时候,平衡二叉树的树高度很高。这意味着当需要通过遍历获取存储在硬盘上的数据时候,需要更多次的I/O操作。硬盘读取时间远远超过数据在内存中比较的时间,这将导致程序大部分时间会阻塞在硬盘 I/O 上。

B树
跟平衡二叉树的不同是,B树是一种多叉树。阶数m决定了B树的节点大小和树的高度。较大的阶数可以容纳更多的键值对,减少树的高度和硬盘访问次数。
B树中每个节点都存放着索引和数据,从下图可见,查询索引为 50 的节点就在第一层,B树只需一次硬盘 I/O 即可完成查找。因此B树的查询最好时间复杂度是 O(1)。

image.png

B+树
B+树是B树的一种变种,它与B树的区别是:
叶子节点保存了完整的索引和数据,而非叶子节点只保存索引值。所以查询索引为 50的数据,必须要遍历到叶子节点才能取到,因此查询时间固定为 O(logn)。
常见的B+树阶数可以是100或更大,以适应硬盘上的大量数据。

image.png

数据查询
B树的范围查询,比如上图要查询“大于10小于30的数据”,需要进行4次硬盘的随机 I/O 。范围查询的随机 I/O次数不稳定和放大,也是 B 树最大的性能问题:
1)遍历根节点的第一个元素是25,大于 10。
2)遍历左子节点的元素,找到第一个大于10的数据是11。
3)重新遍历根节点,发现不包含小于30的数据。
4)遍历载右子节点的元素,找到最后一个小于30的数据是27。
而B+树叶子节点保存指向下一个叶子节点的指针,叶子节点之间类似于单链表连接起来,因此叶子节点的数据在硬盘里是顺序存储的。当读到某个叶子节点数据时候,硬盘根据局部性原理会提前将相关的数据都读进内存,这使得范围查询和排序很高效。
操作系统在读文件时,根据Page Cache机制将数据加载到页缓存中,页的默认大小是4KB。由于B+树非叶子节点都只是索引值,这就意味B+树一次I/O,相比于B树能读出的索引值更多,从而减少查询时候需要的I/O次数。
不同于操作系统,InnoDB引擎的页大小默认是16KB,如下估算:
1)非叶子节点存放(key,pointer),假设主键ID为bigint类型,长度为8字节,而指针在InnoDB源码中为6字节,一共14字节,即非叶子节点能存放 16KB/14 左右的(key,pointer)。
2)叶子节点中保存的一行记录的数据大小为1KB,大约可以存储16K/1K = 16记录数。
如果B+树高度为2,那么存放总记录数为:根节点指针数单个叶子节点记录行数 = 16KB/14 16 大约 1.8w+ 数据。
如果B+树高度为3,那么存放总记录数为:根节点指针数单个叶子节点记录行数 = 16KB/14 16KB/14 * 16 大约2kw+数据。

数据写入
相比于数据读取场景,B+树在写密集型场景的性能并不理想。这主要原因是:B+树在写入(插入、删除、更新)时,为维持树的平衡,可能触发节点分裂、合并。这些操作可能涉及多个磁盘页的修改,导致随机I/O,且需要更新Page Cache中的对应页,使其失效。因此,在写密集型场景下,B+树性能不如专为写入优化的结构。

image.png

因此B+树也通过一些优化策略来提高写操作的性能。比如使用写缓冲区(Write Buffer)来缓存写操作,然后定期将缓冲区中的数据批量刷入硬盘,将随机I/O合并为后续的顺序I/O。此外可以使用多版本并发控制机制(MVCC)来减少写入时候的锁竞争和提高并发性能。

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!!!

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
存储 SQL 算法
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(一)
前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。 页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到槽,上面的过程都与页的内部结构相关,本文将详细的阐述。
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(一)
|
编译器 Go API
go generate指南:代码自动生成
go generate指南:代码自动生成
3698 0
|
2月前
|
存储 分布式计算 NoSQL
Facebook内部都在用的存储引擎,LSM凭什么能硬扛亿级写入流量?
RocksDB是Meta开源的高性能键值存储引擎,基于LSM树设计,专为高吞吐写入场景优化。其核心包括内存表MemTable、持久化SSTable、预写日志WAL及合并机制,适用于海量数据处理。
84 0
|
5月前
|
传感器 人工智能 安全
运营商三要素API的实战指南:实现 “人 - 证 - 号” 三位一体核验
在数字身份欺诈频发的背景下,传统单点验证已无法满足高安全需求。探数API推出的“运营商三要素核验API”,通过姓名、身份证号、手机号的三重交叉验证,构建起“铁三角”防线,广泛适用于金融、政务、电商等领域。该API支持一致性验证及基础信息返回(可选),具备高准确性与防伪性,远超单一或双因素验证方式。其调用流程简单,提供Python示例代码及异常处理建议,助力打造更安全的数字身份体系,成为连接多领域的关键桥梁。未来,多因子融合的身份认证将成为趋势,而三要素核验API正是当前可信数字身份的重要基石。
543 2
|
存储 NoSQL 关系型数据库
为什么MySQL不使用红黑树做索引
本文详细探讨了MySQL索引机制,解释了为何添加索引能提升查询效率。索引如同数据库的“目录”,在数据量庞大时提高查询速度。文中介绍了常见索引数据结构:哈希表、有序数组和搜索树(包括二叉树、平衡二叉树、红黑树、B-树和B+树)。重点分析了B+树在MyISAM和InnoDB引擎中的应用,并讨论了聚簇索引、非聚簇索引、联合索引及最左前缀原则。最后,还介绍了LSM-Tree在高频写入场景下的优势。通过对比多种数据结构,帮助理解不同场景下的索引选择。
371 6
|
8月前
|
人工智能 自然语言处理 IDE
通义灵码 Visual Studio 终于支持模型切换
如需使用灵码模型选择,需要开发者将灵码 IDE 插件更新到最新版,前往下载安装包安装
472 0
通义灵码 Visual Studio 终于支持模型切换
|
人工智能 IDE Java
AI 代码工具大揭秘:提高编程效率的必备神器!
【10月更文挑战第1天】近年来,人工智能得到了迅猛的发展,并在各行各业都得到了广泛应用。尤其是近两年来,AI开发工具逐渐成为开发者们的新宠,其中 GitHub Copilot 更是引发了无限可能性的探索。
666 9
AI 代码工具大揭秘:提高编程效率的必备神器!
|
弹性计算 自然语言处理 Windows
通义灵码 Visual Studio 下载安装指南(附安装包)
本安装步骤适用于 Windows 10 及以上操作系统中安装和使用通义灵码。
2974 3
|
消息中间件 自然语言处理 负载均衡
RabbitMQ揭秘:轻量级消息队列的优缺点全解析
**RabbitMQ简介** RabbitMQ是源自电信行业的消息中间件,支持AMQP协议,提供轻量、快速且易于部署的解决方案。它拥有灵活的路由配置,广泛的语言支持,适用于异步处理、负载均衡、日志收集和微服务通信等场景。然而,当面临大量消息堆积或高吞吐量需求时,性能可能会下降,并且扩展和开发成本相对较高。
692 0
|
设计模式 编解码 前端开发
WPF技术之UI框架介绍
WPF(Windows Presentation Foundation)是微软公司开发的一种用于创建Windows应用程序的UI框架。它是.NET框架的一部分,是Windows Vista及更高版本操作系统的默认UI框架。
2739 0
WPF技术之UI框架介绍
下一篇
开通oss服务