索引基础
没有索引的表,就像没有目录的书——你只能从第一页翻到最后一页来找一个词。
索引是什么
索引(Index) 是数据库中一种特殊的数据结构,用于加速数据检索。它类似于书籍的目录:你不需要逐页翻书,只需要看目录就能快速定位到目标内容。
在 MySQL 中,索引存储在独立的磁盘文件中(InnoDB 引擎下,索引和数据在同一个表空间文件),每个索引本质上是一棵 B+ 树。
一句话总结
索引 = 排好序的查找数据结构,用空间换时间。
索引为什么快
要理解索引为什么快,先看没有索引时数据库是怎么查数据的。
全表扫描:逐行查找
SELECT * FROM orders WHERE customer_id = 10086;没有索引时,MySQL 从第一行开始,一条一条地比较 customer_id 的值,直到找到匹配的记录或者遍历完所有行。
100 万条数据?最坏情况要比较 100 万次。
索引查找:二分定位
有了索引(假设是 B+ 树索引),查找过程是这样的:
- 从根节点开始,判断目标值在左子树还是右子树
- 逐层向下,直到叶子节点
- 在叶子节点中通过双向链表快速定位
100 万条数据,B+ 树高度约为 3~4 层,最多比较 3~4 次就能找到结果。
这就是索引快的本质:把全表扫描的 O(n) 降到了 O(log n)。
索引的优缺点
索引不是银弹,它有代价。
优点
| 优点 | 说明 |
|---|---|
| 加速查询 | 减少 I/O 次数,显著降低查询时间 |
| 减少服务器扫描量 | 不需要遍历全表 |
| 实现唯一约束 | 唯一索引保证数据唯一性 |
| 支持排序和分组 | 索引本身有序,减少 sort 操作 |
缺点
| 缺点 | 说明 |
|---|---|
| 占用磁盘空间 | 索引文件可能比数据文件还大 |
| 降低写操作性能 | INSERT/UPDATE/DELETE 时需要同步维护索引 |
| 增加维护成本 | 数据变更时,索引需要实时更新 |
| 不是越多越好 | 大量索引反而拖慢写入,浪费空间 |
索引设计的基本原则
不是所有字段都值得建索引,设计索引需要权衡。
适合建索引的字段
- WHERE 子句中频繁使用的字段
- JOIN 的 ON 条件涉及的字段
- ORDER BY 和 GROUP BY 涉及的字段
- 区分度高的字段( cardinality 高,如用户 ID)
- 很少更新的字段(索引维护成本低)
不适合建索引的字段
- 区分度很低的字段(如性别:只有男/女,区分度 50%)
- 频繁更新的字段(每次更新都要维护索引)
- 非常长的字符串字段(用前缀索引除外)
- 查询中几乎不使用的字段(浪费空间)
索引设计经验法则
经验法则:为 WHERE、ORDER BY、GROUP BY 涉及的字段建索引。
一个经典的复合索引设计示例:
-- 经常这样查询:
SELECT * FROM orders WHERE status = 'paid' ORDER BY created_at DESC;
-- 复合索引设计:
CREATE INDEX idx_status_created ON orders(status, created_at DESC);
-- ↑ 等值查询放前 ↑ 排序字段紧随其后这个索引同时覆盖了 WHERE 条件(status)和排序(created_at),查询时可以直接从索引中返回结果,无需回表。
MySQL 索引分类体系
从逻辑上,MySQL 索引分为以下几类:
| 分类角度 | 类型 |
|---|---|
| 数据结构 | B+ 树索引、Hash 索引、R-Tree 索引(空间数据) |
| 物理存储 | 聚簇索引(主键索引)、二级索引(非主键索引) |
| 字段个数 | 单列索引、联合索引(复合索引) |
| 唯一性 | 唯一索引、普通索引 |
关于各种索引类型的详细讲解,参见 索引类型:聚簇/二级/联合/B+树/Hash。
验证索引效果
用 EXPLAIN 可以看到查询是否使用了索引:
-- 查看查询计划
EXPLAIN SELECT * FROM orders WHERE customer_id = 10086;关键字段说明:
| 字段 | 值 | 含义 |
|---|---|---|
| type | ALL | 全表扫描,慢 |
| type | ref, range | 索引扫描,快 |
| key | idx_xxx | 实际使用的索引名 |
| rows | 1000000 | 预计扫描行数 |
详细内容见 EXPLAIN 全字段剖析。
小结
索引是 MySQL 性能优化的核心。理解索引的原理和设计原则,比记住几条优化技巧更重要。
记住三句话:
- 索引用空间换时间:磁盘空间换查询速度
- 索引是排好序的 B+ 树:有序才能二分查找
- 索引不是越多越好:写入变慢,空间膨胀
下一步
索引的底层数据结构是什么?聚簇索引和二级索引有什么区别?
从 索引类型 继续。
