Skip to content

概念卡片:MySQL 索引与 B+ 树

一句话机制

InnoDB 用 B+ 树做索引:主键索引(聚簇索引)的叶子存整行数据,二级索引的叶子存主键值;用二级索引查数据要先查二级树拿到主键、再「回表」查主键树。 索引的本质是用「多叉树降低树高」,让一次查询尽量少读磁盘。

为什么是 B+ 树(不是二叉树)

索引模型等值查询范围查询更新适用
哈希表慢(无序,全扫)等值场景(Memcached/NoSQL)
有序数组快(二分)慢(插入要挪)静态数据
二叉搜索树O(logn)树太高,读磁盘多
B+ 树(N 叉)O(logn)数据库标配

二叉树 100 万节点树高 20,一次查询要读 20 个数据块。B+ 树是 N 叉(InnoDB 的 N≈1200),树高 4 就能存 1200³≈17 亿,查一个值最多读 3 次磁盘——这就是「多叉降低树高、减少磁盘 IO」的核心。

聚簇索引 vs 二级索引

类型叶子存什么别名
主键索引整行数据聚簇索引(clustered index)
非主键索引主键值二级索引(secondary index)

回表select * from T where k=5 用二级索引查,先搜 k 索引树拿到主键 id=500,再回主键索引树搜一次拿整行——多扫一棵树。

避免回表的手段:覆盖索引(查询的字段都在二级索引里,不用回表)+ 尽量用主键查询。

页分裂与页合并

  • 页分裂:B+ 树插入中间值,数据页满了要申请新页挪数据,空间利用率降约 50%
  • 页合并:相邻两页因删除利用率低时合并

自增主键 vs 业务主键

维度自增主键业务主键(如身份证号)
插入追加操作,不触发页分裂无序插入,页分裂频繁
二级索引大小主键 4 字节(int)/8 字节(bigint)主键可能 20 字节(字符串)

主键越短,二级索引叶子越小、越省空间 → 常规业务优先自增整型主键。业务主键只适合「只有一个索引 + 必须唯一」的 KV 场景(无二级索引,不用管叶子大小)。

常见误解(避坑)

  1. ❌ "索引存在内存里"。→ 索引要写磁盘,所以选多叉树而非二叉树来降低树高、减少磁盘 IO。
  2. ❌ "主键和普通索引查起来一样快"。→ 普通索引要回表,多扫一棵主键树。
  3. ❌ "主键随便选个字符串就行"。→ 主键长度会放大到每个二级索引的叶子,字符串主键让所有二级索引变大。
  4. ❌ "索引越细越好"。→ 索引有维护成本(页分裂、写放大),只在查询多、写入少的列建。

关联

最近更新