MySQL 索引本质是为了快速查找数据而设计的排序列表,就像书籍的目录——不用翻完整本书,看目录就能直接定位页码,大幅减少查询耗时。
我从底层结构、工作原理、类型、优缺点讲,让新手也能完全理解。
一、核心:索引的底层数据结构
MySQL 索引默认使用 B+ 树(InnoDB 存储引擎),这是索引高效的核心原因。
1. 为什么不用哈希/二叉树?
- 哈希索引:等值查询极快,但无法范围查询(如
where id > 100),不适合业务场景; - 普通二叉树:数据有序时会变成链表,查询退化为全表扫描;
- B 树:节点存数据,范围查询需要遍历整棵树,效率低。
2. B+ 树的核心优势(索引的灵魂)
- 多路平衡:树高极低(千万级数据仅 3-4 层),查询速度稳定;
- 叶子节点相连:所有数据存在叶子节点,且用双向链表串联;
- 非叶子节点只存键值:占用空间极小,能全部加载到内存,避免磁盘IO。
✅ 一句话总结:B+ 树让 MySQL 无论查询、范围查询、排序、分页,都能做到最少磁盘IO、最快速度。
二、InnoDB 索引的两种核心类型
InnoDB 是 MySQL 默认引擎,索引和数据存在同一个文件,分为两类:
1. 聚簇索引(Clustered Index)
- 定义:主键索引就是聚簇索引,数据直接存放在索引的叶子节点上;
- 特点:
- 一张表只有一个聚簇索引;
- 数据物理存储顺序和索引顺序一致;
- 查询速度最快(直接在索引上拿到完整数据)。
- 无主键时:InnoDB 会自动生成隐藏列作为主键。
2. 二级索引(普通索引/联合索引)
- 定义:除主键外的所有索引(普通索引、唯一索引、联合索引);
- 结构:叶子节点不存完整数据,只存主键值;
- 查询流程:
- 先查二级索引 → 找到对应主键;
- 再用主键查聚簇索引 → 拿到完整数据(这个过程叫回表)。
三、索引工作原理:查询时发生了什么?
举个例子:SELECT * FROM user WHERE id = 100;
- 加载 B+ 树的根节点到内存;
- 比较键值,判断数据在左子树还是右子树;
- 逐层向下查找,只访问 3-4 个节点;
- 定位到叶子节点,直接读取数据。
✅ 无索引:全表扫描(逐行遍历,千万数据秒级响应) ✅ 有索引:B+ 树查找(毫秒级响应)
四、最左前缀原则(联合索引核心原理)
联合索引 (a, b, c) 本质是按 a 排序 → a 相同按 b 排序 → b 相同按 c 排序的 B+ 树。
生效规则:
- ✅
where a=1→ 生效 - ✅
where a=1 and b=2→ 生效 - ✅
where a=1 and b=2 and c=3→ 生效 - ❌
where b=2→ 失效(跳过 a,无法确定范围) - ❌
where a=1 and c=3→ 仅 a 生效(b 断档,c 无法排序匹配)
五、索引的两大关键特性
1. 覆盖索引
查询的字段,全部在索引里,不需要回表,速度极快。
例:索引 (name, age),查询 SELECT name, age FROM user WHERE name = "张三"
→ 直接从索引拿数据,无回表。
2. 索引失效(高频坑点)
这些操作会让索引直接报废:
- 使用函数/运算:
where YEAR(create_time) = 2024 - 隐式类型转换:
where id = "123"(字符串=数字) - 模糊查询以 % 开头:
where name like "%张三" - 使用
!=/is null/or(无索引覆盖时)
六、索引的优缺点(必须知道)
✅ 优点
- 大幅提升查询、排序、分组速度;
- 减少服务器扫描的数据量;
- 避免使用临时表、文件排序。
❌ 缺点
- 占用磁盘空间(索引也是数据);
- 增删改变慢(数据变化时,B+ 树需要重新平衡);
- 过多索引会让优化器选择困难,降低效率。
七、极简总结(核心记忆点)
- 索引 = B+ 树结构 = 排序列表,目的是减少磁盘IO;
- 聚簇索引(主键):叶子节点存完整数据,最快;
- 二级索引:叶子节点存主键,查询需要回表;
- 联合索引:遵循最左前缀原则;
- 覆盖索引:避免回表,性能最优;
- 索引能加速查询,但会拖慢写入,不能滥用。
总结
- MySQL 索引底层是 B+ 树,这是高效查询的核心;
- 主键索引是聚簇索引,数据直接存在索引上;
- 联合索引必须遵守最左前缀原则;
- 合理使用覆盖索引,避免回表和索引失效。