MySQL索引优化核心是命中合适索引并避免失效:高选择性列优先建索引;联合索引遵循最左前缀原则;避免在索引列上使用函数或表达式。

MySQL 查询性能优化的核心之一是合理使用索引。索引不是越多越好,关键在于让查询能命中合适的索引,并避免索引失效。
选择性高的列优先建索引
索引效果取决于列的区分度(即不同值的数量占比)。例如用户表中的 email 字段通常唯一或接近唯一,比 gender(只有男/女)更适合建索引。查询时如果 WHERE 条件用到低选择性字段(如 status=1),即使有索引,MySQL 也可能放弃使用而走全表扫描。
- 用 SELECT COUNT(DISTINCT col)/COUNT(*) FROM table 估算选择性,越接近 1 越适合索引
- 联合索引中,把选择性高的列放在前面
遵循最左前缀原则使用联合索引
联合索引 (a,b,c) 实际上等价于三个索引:(a)、(a,b)、(a,b,c)。WHERE 条件必须包含最左列 a 才可能用上该索引。
- ✅ WHERE a = 1 AND b > 10 可用索引
- ✅ WHERE a = 1 AND b = 2 AND c IN (3,4) 可用索引
- ❌ WHERE b = 2 AND c = 3 无法使用该联合索引
- ⚠️ WHERE a = 1 AND c = 3 只能用到 a 列,c 无法走索引(b 缺失导致断层)
避免常见索引失效场景
即使字段上有索引,以下写法也会导致索引失效:
- 在索引列上使用函数或表达式:WHERE YEAR(create_time) = 2023 → 改为 WHERE create_time >= '2023-01-01' AND create_time
- 隐式类型转换:WHERE phone = 13800138000(phone 是 VARCHAR)→ 改为加引号:'13800138000'
- LIKE 以通配符开头:WHERE name LIKE '%abc' → 无法使用索引;LIKE 'abc%' 可以
- 使用 != 或 NOT IN(尤其对 NULL 敏感)→ 尽量改用范围或 EXISTS
用 EXPLAIN 验证索引是否生效
执行 EXPLAIN SELECT ... 查看执行计划,重点关注:
- type:尽量达到 range、ref;避免 ALL(全表扫描)和 index(全索引扫描)
- key:显示实际使用的索引名;NULL 表示未用索引
- rows:预估扫描行数,越小越好
- Extra:出现 Using filesort 或 Using temporary 是性能隐患信号
不复杂但容易忽略。










