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 分析执行计划,可以快速定位索引失效的具体原因,从而采取针对性的修正措施。

相关推荐
aiks_yuan14 小时前
MySQL 深分页 LIMIT 越翻越慢怎么办:300 万行实测 OFFSET、延迟关联和 keyset 的耗时差距(MySQL 8.2)
mysql
Decay__14 小时前
14_MySQL 高可用与容灾架构 —— MGR / InnoDB Cluster / Keepalived+VIP / 双主 / 读写分离 / 两地三中心
运维·数据库·sql·mysql·架构
Thanks_ks17 小时前
MySQL 的索引是什么?用图书馆的目录讲明白
数据库·sql·mysql·索引·联合索引·explain·慢查询优化
.痞老板.1 天前
mysql初阶--增删改查操作
数据库·mysql
浮生若城2 天前
MySQL:库与表的操作
数据库·mysql
翔云1234562 天前
RocksDB中,客户端每写入一次数据,需要访问几次磁盘
运维·数据库·mysql
在多学一点2 天前
MYSQL第二次作业
android·数据库·mysql
yeccheng2 天前
MySQL 索引超详解:从底层 B+ 树到面试高频考点
java·开发语言·jvm·mysql·面试
骑着蜗牛撵大象3272 天前
MySQL 8.0 迁移后 SQL 变慢:执行计划里 3 类被忽略的成本差异
android·数据库·sql·mysql·优化器·执行计划
.痞老板.3 天前
mysql初阶--数据类型
android·数据库·mysql