面试被问到 MySQL 索引,多数人的回答停留在"加快查询"四个字。
这话对,但没用。
索引真正要讲清楚的,是一份排好序的目录:
索引可以理解成一份排好序的目录,它通过维护特定的数据结构,让数据库能够更快定位目标数据,而不必每次都扫描整张表。
代价也实打实------写数据时要顺手维护它,空间上多占一份。
用写入和空间换查询速度,这层账得算明白。
索引到底是什么
拿查字典说最清楚。
没有目录,找一个字得从第一页翻到最后一页,数据库管这叫全表扫描。
有了拼音目录,先定位到那一页再细看,这就是索引查找。
MySQL 的索引就是这张目录。
它是存储引擎层建的辅助数据结构, 以 InnoDB 的 B+ 树索引为例,它会按照索引列的值组织数据,使查询能够沿着索引结构快速定位目标记录。
说白了,索引在存储引擎层,不在 Server 层。
不同存储引擎的索引实现走的不是一条路,InnoDB 和 MyISAM 就是两套完全不同的方案,后面细说。
底层为什么是 B+ 树
面试官八成会追问:
凭什么用 B+ 树,不用 B 树?
官方文档写的是 "B-tree",但面试和平时交流里一定说 B+ 树。
它两个特征最关键:
非叶子节点只存索引键和指针,不存数据,所以同一层能塞下更多键,树更矮;
所有叶子节点用链表串起来,天然有序,范围查询和排序顺着链表走就行。
树矮的意义在 IO。
B+ 树的高度通常比较低,一次索引查找只需要经过少量层级;
如果相关索引页不在 Buffer Pool 中,才需要从磁盘读取,因此能够显著减少磁盘 IO。
树的高度越低,查找需要访问的节点越少,通常也意味着更少的 IO 开销。
二叉树太高、哈希表不支持范围查询和排序,都不如 B+ 树全面。

聚簇、非聚簇,还有回表
这块最容易答偏。
InnoDB 里索引分两类。
聚簇索引的叶子直接存整行,一张表只有一个,通常就是主键。
二级索引的叶子存的是主键值,不是整行。
问题就出在二级索引上。
你写 where name = '张三',引擎先在 name 索引里找到张三对应的主键,再拿主键去聚簇索引把整行捞出来。这多走的一步叫回表。
MyISAM 是另一条路:
它的索引叶子存行号,拿到行号去数据文件按位置读。
所以 MyISAM 没有聚簇的概念,索引全是二级的。

索引不只是加快查询
检索提速、降 IO 是本职。
一张千万级的订单表跑 where order_id = 16815,没索引只能全表扫描把每页读一遍,IO 开销极大;
建了 order_id 索引,可以沿着 B+ 树快速定位目标记录,大幅减少需要扫描的数据页和 IO 开销。
ORDER BY、GROUP BY 在满足索引顺序等条件时,可以利用索引本身的有序性减少排序开销,而不一定需要额外的排序操作。
具体是否使用索引,要结合执行计划判断。
看执行计划 Extra 列,本来会显示 Using filesort,用了索引有序性这一项就消失。
唯一索引还能保数据完整。
主键和唯一索引靠唯一约束挡脏数据,比如用户表给 phone 建唯一索引,重复手机号直接写不进去。这比在 Java 代码里判重可靠,数据库层约束是硬性的,并发下也不会漏。
| 作用 | 说明 |
|---|---|
| 检索提速 | 大幅减少需要扫描的数据页和 IO 开销 |
| 排序 / 分组 | 利用索引有序性,减少额外排序开销 |
| 数据完整 | 唯一 / 主键索引挡住重复脏数据 |
但索引不是免费的。
每次写入,索引都得跟着更新。
B+ 树插入可能引发页分裂,删除可能触发页合并,都是实打实的额外开销。
所以写多读少的表,索引越多写入越慢,反而成了一种负担。
索引本身也会占用额外存储空间,表上索引越多,占用的空间和维护成本通常也越高,不是越多越好。索引多了,优化器选择执行计划的成本也可能增加。
还有一些常见场景会让普通索引难以有效利用,比如 LIKE '%张' 这种左模糊查询、对索引列进行函数计算,以及部分隐式类型转换。
遇到这类情况不要凭感觉判断,最好结合 EXPLAIN 查看实际执行计划。
必要时再考虑其他优化方案,而不是直接依赖 FORCE INDEX。
| 索引难以有效利用的常见场景 | 原因 |
|---|---|
like '%张' 左模糊 |
前缀不确定,B+ 树有序性用不上 |
字段套函数 where year(createtime)=2024 |
索引列被计算,无法命中 |
类型不匹配 where phone = 13800000000(phone 是字符串) |
隐式转换导致索引失效 |
所以这道题别只说"加快查询"。
从 B+ 树结构、InnoDB 的回表、到作用和优缺点体系化讲一遍,面试官才信你是真懂。