MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来

面试中解释 B+ 树,如果只说"树比较矮",还没有说明数据库为什么需要这样的组织方式。关键是数据库按页管理数据,查询要同时考虑点查、范围扫描和写入维护。

从页内导航理解分叉

B+ 树的内部节点主要保存导航所需的信息,叶子节点保存相应的数据记录或索引记录。一个页能容纳较多导航项,便可以指向更多子页,减少访问路径的层数。

这并不意味着一次查询固定产生几次磁盘 I/O。上层页可能已经在缓冲池里,叶子页也可能命中缓存。树高描述结构,实际耗时还受缓存、数据量与访问模式影响。

范围查找为什么适合

假设查询某段时间内的订单,索引先定位到范围起点,再沿叶子层扫描后续记录,直到超过终点。这样能够利用键的顺序组织,减少重新从根开始寻找每条记录的工作。

叶子有顺序联系,不代表磁盘空间完全连续。分页、分裂和维护都会影响实际布局。查询是否高效,仍需要看扫描范围和符合条件的数据量。

哈希结构擅长按键做等值定位,却不能仅靠哈希值自然表达"大于某个日期"的有序范围。二叉平衡树也能维护顺序,但数据库的页结构更适合较大的分叉数。

在 InnoDB 里区分两种叶子记录

InnoDB 聚簇索引的叶子保存行数据,通常由主键组织。二级索引记录则包含索引列和主键列,查询需要额外列时,可以根据主键再访问聚簇索引,这个过程通常叫回表。MySQL 官方索引说明明确描述了这一区别。

假设表有订单 id、创建时间和金额,二级索引按创建时间组织。按日期筛选,再取金额,可能需要从二级索引得到主键,再读取行数据。

如果查询所需的列已经由索引覆盖,就有机会减少为补充列值而访问聚簇索引的工作。不过,事务可见性等因素仍可能影响实际访问,不能把覆盖索引理解为任何情况下都绝不碰行数据。

查询关注点 需要观察的内容
范围是否过大 扫描了多少索引记录
是否需要额外列 是否发生额外的聚簇索引访问
主键是否过长 二级索引占用是否变大
写入是否频繁 额外索引带来的维护成本

索引越多也会增加成本

二级索引包含主键,因此很长的主键会增加二级索引记录的空间。为了覆盖一个查询,把很多大字段加入索引,也会增加存储与写入维护成本。

建索引前先确认真实查询的条件、排序与返回列。使用有代表性的数据查看执行计划、实际扫描和耗时,再和写入成本一起判断。只用几条测试数据,通常很难看到范围变大或回表增加后的区别。

B+ 树提供了适合页存储和有序查询的结构,具体索引仍要围绕业务访问设计。把叶子存什么、查询经过哪里说清楚,回表与覆盖索引就能顺着同一条路径理解。

我是程序员Sunday,本文相关的完整解析收录在 sunday面试指南,可继续阅读《MySQL 索引为什么用 B+ 树?与 B 树、哈希索引有什么区别?》。

相关推荐
程序员塔塔喵18 分钟前
【MySQL篇|第十而二篇】深层次讲解MVCC机制
mysql·mvcc
飞浪纪元[FWC–FE]23 分钟前
Qt 工程创建与 CMake / qmake 构建规范
开发语言·数据库·qt
Ivanqhz27 分钟前
MoE + LLM 应用
数据库·人工智能·pytorch·python·深度学习·算法·1024程序员节
Tsuki_tl33 分钟前
【总结】Redis五大数据类型应用场景及基本命令
数据库·redis·后端·缓存·缓存中间件·redis命令·redis 五大数据类型
Gauss松鼠会33 分钟前
GaussDB 整体架构解析
运维·服务器·网络·数据库·sql·架构·gaussdb
系统集成-鹰翔39 分钟前
ERP对接升级提示数据库迁移失败:SQLite逐版本事务到底回滚到哪一步
javascript·数据库·经验分享·后端
西瓜拿铁好喝39 分钟前
开源和闭源 AI 办公工具,分别适合谁
java·前端·数据库
一技安身40 分钟前
MySQL 8.4.13 LTS 通用二进制包(Linux免安装版)完整教程
linux·mysql·adb
代码派1 小时前
业务不停机迁移 MySQL 到 TiDB,NineData 数据增量同步实操演示
数据库·mysql·tidb·ninedata·无停机迁移·增量迁移·全量迁移
Gauss松鼠会1 小时前
GaussDB 中 gsql 与 DBeaver(JDBC)客户端工具查询时间不一致:原因、排查与处理
运维·服务器·数据库·sql·gaussdb·经验总结