MySQL 索引原理
MySQL 索引是理解数据库查询性能的核心。重点包括 B+Tree、聚簇索引、二级索引、回表、覆盖索引、最左前缀、索引下推、索引失效和 EXPLAIN。
1. 索引是什么
索引是为了加速查询而维护的数据结构。
没有索引时:
全表扫描有索引时:
通过索引快速定位数据索引不是越多越好。索引会提升查询性能,但会增加写入、更新、删除成本,也会占用磁盘空间。
2. 为什么 InnoDB 使用 B+Tree
B+Tree 特点:
- 多叉树,高度低。
- 非叶子节点只存 key 和指针。
- 叶子节点存储完整数据或主键值。
- 叶子节点之间有链表,适合范围查询。
相比二叉树,B+Tree 高度更低,磁盘 IO 更少。
相比 Hash 索引,B+Tree 支持范围查询和排序。
3. 聚簇索引
InnoDB 表数据本身就是按主键组织的一棵 B+Tree。
聚簇索引叶子节点存放完整行数据:
主键 -> 完整行记录所以按主键查询通常很快。
如果表没有显式主键,InnoDB 会选择一个唯一非空索引;如果也没有,会生成隐藏 row id。
4. 二级索引
二级索引也叫辅助索引。
二级索引叶子节点存放:
索引列值 -> 主键值如果查询字段不在二级索引中,需要根据主键再查一次聚簇索引,这个过程叫回表。
5. 回表
示例:
select name, age from user where phone = '13800000000';如果 phone 上有索引,但索引中没有 name、age,流程是:
通过 phone 索引找到主键 id
-> 通过 id 回到聚簇索引
-> 读取完整行回表次数太多会影响性能。
6. 覆盖索引
如果查询需要的字段都在索引中,就不需要回表。
例如联合索引:
index idx_phone_name(phone, name)查询:
select phone, name from user where phone = '13800000000';只查索引就能返回结果,这就是覆盖索引。
7. 最左前缀原则
联合索引:
index idx_a_b_c(a, b, c)可以命中:
where a = ?
where a = ? and b = ?
where a = ? and b = ? and c = ?不能很好命中:
where b = ?
where c = ?
where b = ? and c = ?因为联合索引按从左到右排序,查询必须从最左列开始使用。
8. 范围查询后的列
联合索引中,如果某列使用范围查询,后续列通常不能继续用于精确定位。
例如:
where a = ? and b > ? and c = ?索引可以有效使用 a 和 b,但 c 很难继续用于缩小扫描范围。
9. 索引下推
索引下推(Index Condition Pushdown)是 MySQL 的优化。
没有索引下推时,存储引擎通过索引找到记录后,需要回表交给 Server 层判断其他条件。
有索引下推时,能在存储引擎层先用索引中的字段过滤一部分数据,减少回表。
10. 索引失效场景
常见场景:
- 对索引列使用函数。
- 对索引列进行计算。
- 隐式类型转换。
- 联合索引不满足最左前缀。
- 前置
%的like。 or两边不是都有索引。- 数据区分度太低,优化器认为全表扫描更划算。
示例:
where date(create_time) = '2026-06-22'对索引列使用函数,可能导致索引失效。更好的写法是:
where create_time >= '2026-06-22 00:00:00'
and create_time < '2026-06-23 00:00:00'11. EXPLAIN 重点字段
| 字段 | 含义 |
|---|---|
type | 访问类型 |
possible_keys | 可能使用的索引 |
key | 实际使用的索引 |
rows | 预计扫描行数 |
filtered | 条件过滤比例 |
Extra | 额外信息 |
type 常见性能从好到差:
system -> const -> eq_ref -> ref -> range -> index -> ALL看到 ALL 要警惕全表扫描。
12. 理解检查
为什么建议主键递增?
递增主键插入更接近顺序写,减少页分裂和随机 IO。UUID 作为主键可能导致索引页频繁分裂。
什么是回表?
通过二级索引找到主键后,再通过主键查询聚簇索引获取完整行。
什么是覆盖索引?
查询所需字段都在索引中,无需回表。
索引是不是越多越好?
不是。索引会增加写入成本和存储成本,也会影响优化器选择。
13. 总结
MySQL 索引的核心是 B+Tree。聚簇索引存完整行,二级索引存主键,回表影响性能,覆盖索引能减少回表。联合索引设计要遵守最左前缀,并结合查询条件和区分度。