MySQL 中的索引 本质上是一种用于加速数据检索的数据结构 。理解索引,核心抓住三点:是什么、怎么用、什么时候会失效。
一、索引是什么 & 为什么快
索引类似书的目录:
- 不用从头到尾扫描(全表扫描)
- 通过有序结构,快速定位数据行
在 InnoDB 中,索引的底层实现是 B+Tree。
为什么是 B+Tree?
- 树高度低(通常 2~4 层)
- 叶子节点有序 + 双向链表
- 范围查询效率极高
- 适合磁盘 IO(一次 IO 读一个页)
二、MySQL 索引的分类(按逻辑)
1. 主键索引(PRIMARY KEY)
- 表中唯一
- 不允许
NULL - InnoDB 中是聚簇索引
sql
PRIMARY KEY (id)
数据本身存放在主键 B+Tree 的叶子节点中
2. 普通索引(INDEX)
- 仅用于加速查询
- 可重复、可为 NULL
sql
CREATE INDEX idx_name ON user(name);
3. 唯一索引(UNIQUE)
- 值必须唯一(NULL 除外)
sql
CREATE UNIQUE INDEX uk_email ON user(email);
4. 联合索引(复合索引)
- 多个字段组成
- 最左前缀原则
sql
CREATE INDEX idx_abc ON t(a, b, c);
✅ 能用索引的情况:
aa, ba, b, c
❌ 不能直接用:
bb, c
5. 全文索引(FULLTEXT)
- 用于文本搜索(
MATCH ... AGAINST) - 常用于文章、评论
sql
FULLTEXT(title, content)
三、聚簇索引 vs 非聚簇索引(重点)


🔹 聚簇索引(Clustered Index)
- 主键索引
- 叶子节点 = 整行数据
- 一张表只能有一个
🔹 二级索引(辅助索引)
-
叶子节点存的是:主键值
-
查询流程:
- 先走二级索引
- 拿到主键
- 再回表查数据(回表)
覆盖索引可以避免回表
四、覆盖索引(非常重要)
sql
SELECT name FROM user WHERE name = 'Tom';
name字段有索引- 查询字段 全在索引中
Extra: Using index
✅ 性能最好
五、索引什么时候会失效(高频面试)
❌ 以下情况索引可能失效:
- 最左前缀被破坏
sql
WHERE b = 2 AND c = 3
- 对索引列使用函数
sql
WHERE DATE(create_time) = '2026-01-01'
- 隐式类型转换
sql
WHERE phone = 13800138000 -- phone 是 varchar
LIKE '%xxx'
sql
LIKE '%abc'
- OR 条件一边没索引
sql
WHERE a = 1 OR b = 2
六、如何判断索引是否生效
1. EXPLAIN
sql
EXPLAIN SELECT * FROM user WHERE email = 'a@b.com';
重点字段:
-
type(性能从好到差)
const > ref > range > index > ALL -
key:使用的索引 -
rows:扫描行数 -
Extra:Using index(覆盖索引)Using whereUsing filesort(危险)
七、索引设计原则(实战)
✅ 该建索引
- 高频
WHERE - 高频
JOIN - 高频
ORDER BY - 区分度高的字段
❌ 不建议建索引
- 更新极其频繁的字段
- 区分度很低(如性别)
- 小表(数据量 < 1w)
联合索引优于多个单列索引
八、面试一句话总结
MySQL InnoDB 使用 B+Tree 作为索引结构,主键索引是聚簇索引,数据行存储在主键索引的叶子节点中,普通索引需要回表;合理使用联合索引、覆盖索引,并遵循最左前缀原则,才能发挥索引的最大性能。