MySQL 索引优化实战:最左前缀、失效场景与覆盖索引

一、先分清索引类型

类型 说明
聚簇索引 InnoDB 主键即聚簇,叶子存整行,每张表只有一个
二级索引 叶子存主键值,查非索引列需回表
覆盖索引 查询列都在索引里,无需回表,最快
联合索引 多列组合,遵循最左前缀

二、最左前缀原则

联合索引 (a, b, c) 能命中:a、(a,b)、(a,b,c);跳过头列如 WHERE b=1 用不上索引。因此把区分度高、最常用作过滤的列放最左。

三、索引失效的常见写法

写法 后果
对索引列做函数/运算 WHERE YEAR(created) = 2024 失效
隐式类型转换 字符串列用数字查,触发转换失效
前导模糊 LIKE ‘%abc’ 失效,’abc%’ 可用
范围后列失效 (a, b) 中 a 用范围,b 不再走索引
OR 含非索引列 整体可能放弃索引
-- 命中索引(走 a 前缀)
SELECT id FROM t WHERE a = 1 AND b = 2;
-- 失效(对列用了函数)
SELECT id FROM t WHERE DATE(created) = '2024-01-01';

四、覆盖索引与回表

尽量让高频查询走覆盖索引,避免回表 IO。例如为 SELECT user_id, status FROM orders WHERE user_id=? 建 (user_id, status) 联合索引即可覆盖。

五、前缀索引与选择性

长字符串(如 URL、邮箱)用前缀索引省空间:ALTER TABLE t ADD INDEX idx(url(20)),但前缀无法用于 ORDER BY / GROUP BY 的范围。权衡:选择性 = 不重复值/总数,越接近 1 越好。

六、EXPLAIN 看什么

  • type:从好到差 const > eq_ref > ref > range > index > ALL,ALL 是是全表扫描;
  • key:实际用的索引;
  • rows:预估扫描行数,越小越好;
  • Extra:Using index 覆盖、Using filesort 需优化、Using temporary 危险。

索引优化的第一性原理:让查询尽可能用上索引、少回表、少扫描。EXPLAIN 是你和 MySQL 优化器对话的窗口。