MySQL 索引失效的三种典型场景与 EXPLAIN 分析
在 MySQL 生产环境中,索引失效是导致查询性能下降的常见原因。本文通过 EXPLAIN 执行计划,分析三种典型的索引失效场景,并给出对应的修正方法。
隐式类型转换:字符串字段未加引号
当字段定义为 varchar,查询时却使用数字,MySQL 会进行隐式类型转换,导致索引失效。
sql
EXPLAIN SELECT * FROM user WHERE phone = 13800138000;
输出/效果说明 :执行计划中 type 显示为 ALL(全表扫描),key 为 NULL。因为 MySQL 为了匹配数字,会把表中所有 phone 字段转为数字再比较,索引树无法利用。
修正 :加上单引号 WHERE phone = '13800138000',type 变为 ref,索引生效。
最左前缀断裂:模糊查询开头通配符
联合索引遵循最左前缀原则。如果在 like 查询中开头使用 %,索引树无法从左向右匹配,只能放弃索引。
sql
EXPLAIN SELECT * FROM user WHERE name LIKE '%张';
输出/效果说明 :type 显示为 ALL,Extra 显示 Using where。因为索引是有序排列的,'%张' 意味着张可能在任何位置,B+ 树无法定位起始点,只能全表扫描。
修正 :改为 LIKE '张%' 可走索引;若必须模糊匹配,考虑使用覆盖索引或 Elasticsearch。
列上使用函数:函数操作破坏索引结构
在 WHERE 条件中对索引列进行函数运算,会导致 MySQL 无法直接使用索引值,必须逐行计算后再比较。
sql
EXPLAIN SELECT * FROM user WHERE YEAR(create_time) = 2023;
输出/效果说明 :type 为 ALL,key 为空。虽然 create_time 有索引,但函数操作迫使引擎取出每一行数据计算年份,索引排序特性被破坏。
修正 :改为范围查询 WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31',type 变为 range。
索引使用检查清单
-
检查字段类型与查询值是否一致,避免隐式转换。
-
联合索引查询是否命中最左列,避免中间断裂。
-
WHERE 条件列是否保持纯净,避免函数和计算。
-
OR 连接条件中,只要有一列没有索引,整个索引失效。
-
定期使用慢查询日志配合 EXPLAIN 复盘线上 SQL。
索引优化不是堆数量,而是理解其原理。通过 EXPLAIN 分析执行计划,可以快速定位索引失效的具体原因,从而采取针对性的修正措施。