MySQL 索引失效的三种典型场景与 EXPLAIN 分析

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。

索引使用检查清单

  1. 检查字段类型与查询值是否一致,避免隐式转换。

  2. 联合索引查询是否命中最左列,避免中间断裂。

  3. WHERE 条件列是否保持纯净,避免函数和计算。

  4. OR 连接条件中,只要有一列没有索引,整个索引失效。

  5. 定期使用慢查询日志配合 EXPLAIN 复盘线上 SQL。

索引优化不是堆数量,而是理解其原理。通过 EXPLAIN 分析执行计划,可以快速定位索引失效的具体原因,从而采取针对性的修正措施。

相关推荐
这个DBA有点耶1 小时前
连接数没满,应用却连不上数据库——TCP backlog溢出与somaxconn的隐藏限制
数据库·mysql·代码规范
小羊没烦恼!2 小时前
C#综合揭秘——Entity Framework 并发处理详解
java·开发语言·前端·javascript·数据库·mysql·c#
flytalei3 小时前
从 Docker Compose 到 K3s:逐浪博客 MySQL 数据迁移实战与一致性验证
mysql·docker·容器
SL_staff4 小时前
3分钟上线新规则:业务人员拖拽完成合同超期自动暂停服务
java·mysql·全栈
CS创新实验室4 小时前
数据库突然断电,凭什么没丢数据?——WAL 日志与崩溃恢复
数据库·mysql
用户84913717547165 小时前
【技术干货】MySQL联合索引底层原理 | 最左前缀原则详解
mysql·面试
kele_z5 小时前
手工修改数据库中的数据时,我会加的四道保险
mysql·postgresql
ly76895 小时前
PostgreSQL 执行计划深读:从 EXPLAIN 输出到代价模型驱动的 SQL 改写
数据库·sql·postgresql·explain·执行计划·代价模型
eleven_4u6 小时前
MySQL深分页如何处理
mysql