【大白话说Java面试题 第71题】【Mysql篇】第1题:索引是什么?
📌PDF:大白话说Java面试题 — 03-Mysql篇
第1题:索引是什么
📚回答:
- 核心考点:
索引是数据库性能优化的核心手段。大厂面试要求能说出本质(数据结构)、作用(快 vs 慢)、代价(存储 + 写放大),并能解释为什么不是越多越好。
1. 索引的本质
定义:
索引是排好序的数据结构(MySQL InnoDB默认为B+Tree),用于快速定位数据行,避免全表扫描。时间复杂度对比:
- 无索引:全表扫描 O(N)
- 有索引(B+Tree):O(log N)
2. 索引的工作原理(B+Tree简解)
| 特性 | 说明 |
|---|---|
| 多路平衡树 | 每个节点存储多个key,树高度低(通常2~4层) |
| 叶子节点存放数据(聚簇索引)或主键值(二级索引) | 数据只存在叶子节点 |
| 叶子节点双向链表 | 支持范围扫描(BETWEEN、>、<) |
| 非叶子节点只存key + 指针 | 可全部缓存在内存中,加速查找 |
图示逻辑:
[根节点] → 分支节点 → 叶子节点(数据页) → 叶子节点 → 叶子节点(双向链表)3. 索引的类型与特点
| 索引类型 | 说明 | 叶子节点内容 | 是否必须回表 |
|---|---|---|---|
| 主键索引(聚簇索引) | 表的主键自动建立 | 完整行数据 | 否 |
| 二级索引(非聚簇索引) | 普通/唯一/联合索引 | 主键值 | 是(需回表) |
| 唯一索引 | 列值唯一,可null | 同二级索引 | 是 |
| 联合索引 | 多列组合 | 主键值 | 是 |
| 全文索引 | 文本分词检索 | 特殊格式 | 特殊 |
| 哈希索引(Memory引擎) | 等值查询快 | 数据指针 | 不支持范围 |
关键点:
- 每张表只有一个聚簇索引(主键无则选第一个唯一非空列,再无则隐藏row_id)
- 二级索引查到的只是主键值,需要再查主键索引才能得到完整行 →回表
4. 索引的优缺点(面试必背)
| 优点 | 缺点 |
|---|---|
| 查询速度提升(O(N) → O(log N)) | 占用额外磁盘空间(通常为数据的1%~5%) |
| 唯一索引保证数据唯一性 | INSERT/UPDATE/DELETE 变慢(需同步更新索引) |
加速排序(ORDER BY) | 索引过多影响写性能,优化器选错索引 |
加速分组(GROUP BY) | 过长字段建索引浪费空间 |
公式:
索引不是越多越好。读多写少可多建,写多读少需控制数量。
5. 联合索引与最左前缀原则(高频面试题)
联合索引示例:INDEX(a, b, c)
| 查询条件 | 是否使用索引 | 使用哪些列 |
|---|---|---|
WHERE a = 1 | ✅ | a |
WHERE a = 1 AND b = 2 | ✅ | a, b |
WHERE a = 1 AND b = 2 AND c = 3 | ✅ | a, b, c |
WHERE a = 1 AND c = 3 | ✅(部分) | a(c用索引下推) |
WHERE b = 2 | ❌ | 无(缺最左列a) |
WHERE a = 1 ORDER BY b | ✅ | a 索引,b 利用排序 |
WHERE a = 1 ORDER BY c | ✅(但需filesort) | a 索引,c 不能直接排序 |
最左前缀原则:
- 查询条件必须从索引最左列开始,且不能跳过中间列
- 跳过一列,后面的列无法用于索引查找,但可能用于索引下推(ICP)
6. 回表与覆盖索引(大厂深度)
回表:
- 二级索引查到主键 → 再去聚簇索引查完整行
- 代价:每次回表是一次随机I/O,回表行数多时性能下降
覆盖索引:
- 当查询的所有列都在索引中时,不需要回表
- 示例:
-- 索引:INDEX(name, age)SELECTname,ageFROMuserWHEREname='张三';-- 覆盖索引,不回表SELECTname,age,idFROMuserWHEREname='张三';-- 回表(id可能不在索引)
优化技巧:把频繁查询的字段放入联合索引,变成覆盖索引。
7. 索引失效典型场景(面试必考)
| 场景 | 原因 | 示例(假设索引name) |
|---|---|---|
| 函数操作 | 索引列被计算/函数 | WHERE LOWER(name) = 'zhang' |
| 隐式类型转换 | 字符串列传int | WHERE name = 123(转字符串比) |
使用!=或<> | 不等号很难用索引 | WHERE age <> 30 |
LIKE '%abc' | 通配符开头的模糊匹配 | WHERE name LIKE '%张' |
OR未全索引 | OR两边不全有索引 | WHERE name='a' OR age=30(age无索引) |
| 联合索引不遵循最左前缀 | 缺少最左列 | 索引(a,b),WHERE b=1 |
8. 面试官追问示例
Q1:为什么不建议在低基数列(如性别)建索引?
A:低基数(如性别只有男/女)索引选择性差。查询WHERE gender='男'可能返回50%数据,优化器会全表扫描而不是用索引。
Q2:B+Tree和B-Tree区别?
A:B+Tree非叶子节点不存数据,叶子节点存全部数据且双向链表,更适合范围查询和顺序扫描。MySQL InnoDB使用B+Tree。
Q3:主键用UUID有什么问题?
A:UUID随机无序,插入时页分裂频繁,写性能差;且占用16字节,二级索引叶子节点存储主键值,空间浪费大。推荐自增整型/BigInt。
Q4:什么是索引下推(ICP)?
A:MySQL 5.6+优化。联合索引中,存储引擎层先过滤可用的索引列,减少回表次数。比如INDEX(a,c)查WHERE a=1 AND c=2,先用c=2过滤再回表。
Q5:一条查询同时有联合索引(a,b)和单列索引a,优化器会选哪个?
A:通常选(a,b),因为能覆盖更多条件。但优化器会基于代价估算(IO+CPU),如果a列重复度高可能走单列。
9. 总结对比表
| 维度 | 无索引 | 有索引 |
|---|---|---|
| 查询速度 | 慢(全表扫描) | 快(O(log N)) |
| 写入速度 | 快 | 慢(需维护索引) |
| 磁盘占用 | 低 | 高(额外空间) |
| 维护成本 | 无 | 高(索引选择、重建) |
💡面试官想要的满分总结:
“索引本质上是排好序的B+Tree数据结构,通过二分查找和树的高度压缩实现快速数据定位,避免全表扫描。
优点是查询效率极高,缺点是占用磁盘、拖慢写操作。
需掌握聚簇/二级索引区别、最左前缀原则、回表与覆盖索引,并熟悉索引失效的典型场景(函数、隐式转换、LIKE ‘%…’)。
生产建索引口诀:等值查前置、区分度高的靠前、覆盖索引优化回表、写多读少谨慎加。”
觉得对您有帮助,麻烦点点关注啦,您的关注是我创作的最大动力~ 🎯
