MySQL 索引优化全指南(实战版)

4 阅读3分钟

索引是 MySQL 提升查询速度的核心手段,但用错反而会拖慢性能。我给你整理了最实用、最常用、能直接落地的索引优化方案,从原理到实战一步到位。

一、先搞懂:索引是什么?

简单说:索引 = 数据库的目录

  • 没有索引:全表扫描(逐行找)
  • 有索引:二分查找/树查找(快速定位)
  • 代价:会占用磁盘空间,增删改变慢(因为要维护索引)

二、最核心的索引优化规则(必看)

1. 最左前缀原则(联合索引关键)

联合索引 (a, b, c) 生效规则:

  • where a=? → 生效
  • where a=? and b=? → 生效
  • where a=? and b=? and c=? → 生效
  • where b=? → 不生效
  • where c=? → 不生效
  • where a=? and c=? → 只用到 a

建联合索引口诀: 等值放前面,范围放最后;区分度高放前面

2. 不要在索引列上做运算/函数

索引一旦被计算,直接失效:

-- 坏:索引失效
where date(create_time) = '2025-01-01'

-- 好:索引生效
where create_time >= '2025-01-01 00:00:00' 
  and create_time < '2025-01-02 00:00:00'

3. 尽量使用覆盖索引(避免回表)

查询只查索引里有的字段,不用查原表:

-- 索引 (name, age)
select name,age from user where name='张三' 
-- 直接从索引取数据,极快

4. 模糊查询 like 优化

  • like '张%' → 索引生效
  • like '%张' / like '%张%' → 索引失效

大量模糊搜索建议用:ES、Meilisearch

5. 避免 select *

永远只查需要的字段,减少回表、减少IO。

6. or 会导致索引失效

-- 坏:即使 name 有索引也会失效
where name='张三' or age=20

解决:拆成两条 SQL 或用 union

7. 区分度低的字段不要建索引

比如:性别、状态(0/1) 区分度 = 不重复值数量 / 总行数 区分度 < 20% 不建议建索引

8. 单表索引数量控制

建议:单表索引 ≤ 5 个 联合索引字段 ≤ 3 个

三、索引类型与最佳使用场景

索引类型适用场景
主键索引必须有,自增ID最好
唯一索引手机号、身份证、订单号
普通索引常用查询条件
联合索引多条件组合查询(最常用)
全文索引文章、内容搜索(MySQL自带较弱)

四、建索引黄金法则

  1. where 经常用到的字段
  2. order by / group by 字段
  3. join 关联字段
  4. 区分度高的字段优先
  5. 组合查询建联合索引
  6. 不常更新的表适合建索引

五、不建索引的场景

  1. 少量数据表(<1000行)
  2. 频繁增删改的表
  3. 区分度极低的字段
  4. 查询极少用到的字段

六、实战:如何检查索引是否生效?

explain 分析 SQL:

explain select * from user where name='张三';

重点看 2 个字段:

  • type:最优 → 最差 system > const > eq_ref > ref > range > index > ALL ALL = 全表扫描(必须优化)
  • key:显示使用的索引名 → 为空=没用到索引

七、最常见的错误索引用法

  1. 单字段索引建太多
  2. 联合索引顺序乱建
  3. 索引列上使用函数
  4. 大量使用 %xxx%
  5. 不加区分度盲目建索引
  6. or 连接多个索引字段

八、快速优化模板(直接套用)

假设表:user(id, name, age, city, create_time) 常用查询:

select name,age from user 
where city=? and age>? 
order by create_time desc;

最优索引:

create index idx_city_age_createtime on user(city, age, create_time);

总结

  1. 联合索引遵循最左前缀
  2. 索引列不运算、不函数
  3. 多用覆盖索引避免回表
  4. like %xxx 索引失效
  5. explain 检查索引是否生效
  6. 单表索引不超过5个