如何在where条件中使用索引_mysql条件优化

来源:这里教程网 时间:2026-02-28 20:43:49 作者:

在 MySQL 中,WHERE 条件能否走索引,不取决于写法多“标准”,而取决于是否符合索引的最左前缀原则、字段是否发生隐式转换、以及操作符是否支持范围扫描。很多查询明明建了索引却没用上,问题往往出在条件写法细节上。

确保满足最左前缀原则

联合索引(如

INDEX idx_name_age_city (name, age, city)
)只有从最左边列开始连续匹配,才能有效利用索引:

WHERE name = '张三'
→ 走索引
WHERE name = '张三' AND age > 25
→ 走索引(name 精确 + age 范围)
WHERE name = '张三' AND age = 28 AND city = '北京'
→ 全部走索引
WHERE age = 28
→ 不走索引(跳过最左列 name)
WHERE city = '北京'
→ 不走索引(未包含 name 和 age)
⚠️
WHERE name LIKE '%三'
→ 不走索引(左模糊,无法定位起始位置)
WHERE name LIKE '张%'
→ 可走索引(右模糊或全匹配可利用 B+ 树结构)

避免隐式类型/字符集转换

当 WHERE 字段与条件值类型不一致,或字段定义与传入值字符集不同,MySQL 会自动转换,导致索引失效:

WHERE user_id = '123'
(user_id 是 INT)→ MySQL 把字符串转为数字,但可能放弃索引(尤其在老版本)
✅ 应写成
WHERE user_id = 123
WHERE mobile = 13812345678
(mobile 是 VARCHAR)→ 数字常量触发隐式转换,可能全表扫描
✅ 应写成
WHERE mobile = '13812345678'
⚠️ 若字段是 utf8mb4,但连接字符集是 latin1,也可能触发转换失效索引(可通过
SHOW VARIABLES LIKE 'character_set%'
检查)

慎用非SARGable表达式

SARGable(Search ARGument Able)指能被数据库引擎直接用于索引查找的条件。对字段使用函数、运算或 NOT,通常会让索引失效:

WHERE YEAR(create_time) = 2023
→ 函数作用于字段,无法走索引
✅ 改为
WHERE create_time >= '2023-01-01' AND create_time 
WHERE price * 1.1 > 100
→ 表达式计算在字段上
✅ 改为
WHERE price > 100 / 1.1
WHERE status != 1
→ 非等值且非范围,多数情况下不走索引(除非覆盖且区分度极高)
✅ 如需查少数状态,优先用
IN
或正向条件(如
status IN (2,3)

用 EXPLAIN 验证实际执行路径

别猜,要查。在 SQL 前加

EXPLAIN
,重点关注这几列:

type:至少达到
range
(范围扫描)或更好(
ref
/
eq_ref
)才算有效走索引;
ALL
是全表扫描
key:显示实际使用的索引名;为
NULL
表示没走索引
rows:预估扫描行数,越小越好;远大于结果集说明索引效率低 Extra:出现
Using filesort
Using temporary
常意味着排序/分组未走索引,需结合 ORDER BY 或 GROUP BY 优化

执行后若发现没走索引,先看 warning:

SHOW WARNINGS
,有时会提示“Cannot use ref access on index … due to type or charset mismatch”。

相关推荐