很多人知道索引是数据库性能的关键,但你真的理解它是怎么快起来的吗?
大多数人对索引的理解止步于:
“索引就像书的目录,能快速定位数据。”
这比喻不错,但也太抽象。真正的快,是源于 B+ 树的数据结构设计。今天我们深入聊聊这个数据库性能的基石。
什么是 B+ 树?它和二叉树有什么关系?
B+ 树是一种多路搜索树,是数据库索引的核心数据结构(MySQL 的 InnoDB 默认用的就是 B+ 树)。
它和你熟悉的二叉树、红黑树有几个关键区别:
二叉树最多有两个子节点,B+ 树可以有成百上千个子节点(N 叉树)
B+ 树所有数据都存在叶子节点,内部节点只负责导航
叶子节点之间通过指针连接成链表,方便范围查询
这意味着什么?
B+ 树天生适合磁盘存储 —— 节点数少,层级少,一次 IO 能读很多数据,查得更快。
为什么数据库偏爱 B+ 树?
原因只有一个字:快。
但为什么快?这里有 3 个关键点:
1. 节点容量大,IO 次数少
假设一个 B+ 树节点大小为 16KB,每个键值 8 字节,每个指针 8 字节,那一个节点就能容纳上千个键。
B+ 树高度一般只有 2~4 层,意味着:
查一条数据只需要 2~4 次磁盘 IO,性能非常稳定。
相比之下,红黑树、高度深,查找路径长,不适合落地磁盘结构。
2. 所有值都在叶子节点,支持范围查询
B+ 树把数据都放在最底层的叶子节点,这样范围查询就可以通过叶子节点的链式结构一口气往后扫,非常高效。
比如:
select * from user where age between 20 and 30;
只需定位到第一个 age ≥ 20 的节点,然后顺着链表扫到 age > 30 为止。
顺序 + 范围检索,非常快。
3. 内部节点只存键,不存值,提高分支因子
B+ 树的内部节点只存索引键,不存整行数据,这让它在相同内存页大小下,能容纳更多的键(分支因子高),树的高度就更低。
树矮 = 查找路径短 = IO 次数少 = 查询快。
InnoDB 的聚簇索引和二级索引,怎么用 B+ 树?
在 InnoDB 中,索引分为两种:
聚簇索引(Primary Key)
主键索引的叶子节点存放的是整行数据
每张表只能有一个聚簇索引
执行:
select * from orders where id = 123;
如果 id 是主键,就可以通过 B+ 树直接定位到叶子节点,拿到整行数据,无需回表。
二级索引(Secondary Index)
普通索引(非主键)的叶子节点只存索引键 + 主键值
查整行数据时,还需要回表到主键索引查数据
比如:
select * from orders where user_id = 456;
如果 user_id 是普通索引,先在 user_id 的 B+ 树里查到主键,再回到主键树查整行数据。
这个“回表”过程,是导致一些 SQL 慢的根本原因。
覆盖索引为什么快?也能靠 B+ 树实现吗?
所谓覆盖索引,就是:
查询字段 全部包含在索引中,不需要回表。
举个例子:
select user_id, status from orders where user_id = 456;
如果你建立了联合索引:
create index idx_user_status on orders(user_id, status);
这条 SQL 就可以直接从二级索引 B+ 树中读取所有需要的字段,完全不需要回主键树查整行数据,速度提升巨大。
这就是 B+ 树在实战中的威力。
总结:B+ 树快的本质
它是多叉树,层级少,IO 次数少
所有值都在叶子节点,顺序遍历快
节点间有链表指针,支持范围查询
InnoDB 通过聚簇索引和二级索引机制,结合 B+ 树实现了高效的数据查找
想写出高性能 SQL,理解 B+ 树是底层基础。
真正的数据库高手,不只是“用”索引,而是知道索引为什么快、什么时候失效、如何设计得更好。




