MySQL 索引基础知识
MySQL 索引基础知识
什么是索引
索引是数据库为了加快查询速度而维护的一种有序数据结构,可以类比书的目录:想找某一章的内容,先翻目录定位页码,而不用一页一页往后翻。
没有索引时,MySQL 执行 WHERE user_id = 42 这样的查询,只能全表扫描——把所有行逐条读出来比对。数据量小的时候感觉不到差别,数据量到几十万、几百万行之后,查询就会明显变慢。
MySQL(InnoDB 引擎)的索引使用 B+ 树实现:数据按索引列的值有序存放,查找时沿着树从上往下走,几步就能定位到目标数据,不用逐行扫描。
常见的索引类型
按功能分
| 类型 | 关键字 | 说明 |
|---|---|---|
| 主键索引 | PRIMARY KEY |
每张表只能有一个,值唯一且不能为空,InnoDB 表建表时就应该定义 |
| 唯一索引 | UNIQUE |
值不能重复,可以为空;常用于手机号、订单号这类业务字段 |
| 普通索引 | INDEX / KEY |
最常用的类型,没有唯一性限制 |
| 全文索引 | FULLTEXT |
用于文本关键词搜索,一般业务用得少 |
按字段数量分
- 单列索引:只包含一个字段。
- 联合索引:包含多个字段,如
(user_id, status, created_at)。字段顺序有讲究,见下文。
建索引的基本原则
1. 给经常出现在 WHERE、ORDER BY、JOIN 条件里的列建索引。
-- 这条查询经常跑,就给 user_id、status 建联合索引
ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
2. 优先考虑区分度高的列。
区分度指"这一列不重复的值越多越好"。手机号、用户 ID 区分度高,适合建索引;性别、状态这类只有几个固定取值的列,单独建索引收益很小。
3. 联合索引遵循最左前缀原则。
联合索引 (a, b, c) 相当于按 a 排序、a 相同时按 b 排序、以此类推。所以:
- 查询条件包含
a,可以用上索引; - 包含
a, b或a, b, c,可以完整用上; - 只有
b或只有b, c,用不上这个索引。
因此建联合索引时,把最常用作过滤条件的列放在最前面。
4. 索引不是越多越好。
每个索引都是一棵要维护的 B+ 树,会占用磁盘空间,并且每次 INSERT、UPDATE、DELETE 都要同步更新所有相关索引。一张表的索引控制在合理数量内,写入频繁的表尤其要克制。
常见的索引失效情况
索引建了,写法不对照样用不上。以下几种是最常见的:
1. 对索引列使用函数或运算。
-- 用不上 created_at 上的索引
WHERE DATE(created_at) = '2026-10-16'
-- 改写成范围查询,可以用上
WHERE created_at >= '2026-10-16' AND created_at < '2026-10-17'
2. 隐式类型转换。
-- user_id 是整型,和字符串比较会发生类型转换
WHERE user_id = '42' -- 有失效风险
WHERE user_id = 42 -- 类型一致,稳妥
3. 前导模糊查询。
WHERE name LIKE '%三' -- 用不上索引
WHERE name LIKE '张%' -- 可以用上索引
4. 联合索引查询条件没包含最左列。
-- 索引是 (user_id, status),这个查询用不上它
WHERE status = 'PAID'
如何确认索引有没有生效
用 EXPLAIN 查看执行计划:
EXPLAIN SELECT * FROM orders WHERE user_id = 42;
重点看两个地方:
- key:显示实际使用的索引,为
NULL说明没用上; - type:显示为
ref、range说明走了索引;显示为ALL说明在全表扫描,需要检查索引或改写 SQL。
在开发环境养成先 EXPLAIN 再上线的习惯,是验证索引最直接的方式。
小结
- 索引是有序数据结构,作用是把全表扫描变成快速定位;
- 常用类型:主键、唯一、普通、联合索引;
- 建索引的原则:查询常用的列、高区分度的列、注意最左前缀、数量适度;
- 写 SQL 时避免对索引列做函数运算、类型不一致和前导模糊匹配;
- 上线前用
EXPLAIN确认索引生效。
掌握这些基础内容,日常开发中的大部分索引问题就够用了。
- 点赞
- 收藏
- 关注作者
评论(0)