MySQL 索引失效 20 例

适用 MySQL5.7/8.0 ,默认表:t_user(id PK,uid INT,name VARCHAR(32),phone VARCHAR(11),create_time DATETIME,status TINYINT) 索引: PRIMARY(id)、idx_phone(phone)、idx_name_status(name,status)、idx_ct(create_time)

一、索引列使用函数 / 运算(5 例:1~5)

例 1:索引字段做数学运算

sql

sql 复制代码
-- 失效SQL
SELECT * FROM t_user WHERE id+1=100;
-- 原因:索引列参与算术运算,B+树无法匹配
-- 优化
SELECT * FROM t_user WHERE id=99;

例 2:索引字段套 YEAR () 日期函数

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE YEAR(create_time)=2025;
--优化1(区间,通用)
SELECT * FROM t_user WHERE create_time>='2025-01-01' AND create_time<'2026-01-01';
--优化2 MySQL8.0:函数索引 CREATE INDEX idx_year_ct ON t_user((YEAR(create_time)));

例 3:LEFT/RIGHT 截取字符串

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE LEFT(phone,3)='138';
--优化
SELECT * FROM t_user WHERE phone LIKE '138%';

例 4:TRIM 去除空格函数

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE TRIM(phone)='13800138000';
--优化:入库去空格,查询直接等值
SELECT * FROM t_user WHERE phone='13800138000';

例 5:DATE_FORMAT 格式化索引时间

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE DATE_FORMAT(create_time,'%Y-%m-%d')='2025-05-01';
--优化
SELECT * FROM t_user WHERE create_time>='2025-05-01' AND create_time<'2025-05-02';

二、隐式类型转换(4 例:6~9,高频踩坑)

例 6:字符串索引字段传入数字(phone 是 varchar)

sql

sql 复制代码
--失效:字符串=数字,MySQL隐形转字段为数值
SELECT * FROM t_user WHERE phone=13800138000;
--优化:常量加引号
SELECT * FROM t_user WHERE phone='13800138000';

例 7:int 字段用字符串常量查询

sql

sql 复制代码
--uid int,失效
SELECT * FROM t_user WHERE uid='123abc';
--优化
SELECT * FROM t_user WHERE uid=123;

例 8:JOIN 两边字段类型不一致(user.id int,order.uid varchar)

sql

sql 复制代码
--失效,关联字段类型不一致隐转
SELECT * FROM t_user u JOIN t_order o ON u.id=o.uid;
--优化:统一字段数据类型
alter table t_order modify uid int not null;

例 9:ENUM 与字符串对比隐式转换

sql

sql 复制代码
--status枚举,查询传字符串触发转换
SELECT * FROM t_user WHERE status='1';
--优化:使用定义枚举数值
SELECT * FROM t_user WHERE status=1;

三、条件符号 & 关键字导致失效(6 例:10~15)

例 10:!=、<> 不等于

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE status<>1;
--优化:拆分业务,用正向枚举筛选,status in(0,2)
SELECT * FROM t_user WHERE status IN(0,2);

例 11:NOT IN 非包含查询

sql

sql 复制代码
--失效
SELECT * FROM t_user WHERE uid NOT IN(1001,1002);
--优化:业务拆分,改用LEFT JOIN过滤空值

例 12:IS NOT NULL 非空判断

sql

sql 复制代码
--phone有索引,IS NOT NULL不走索引
SELECT * FROM t_user WHERE phone IS NOT NULL;
--优化:设计字段NOT NULL+默认空串,查询phone<>''

例 13:OR 左右单侧无索引(name 有索引,status 无)

sql

sql 复制代码
--失效:OR一端无索引整句全表扫
SELECT * FROM t_user WHERE name='张三' OR status=1;
--优化:UNION ALL拆分两条SQL
SELECT * FROM t_user WHERE name='张三'
UNION ALL
SELECT * FROM t_user WHERE status=1;

例 14:NOT LIKE 前置通配符 % xxx

sql

sql 复制代码
--失效:前缀%无法走B+树索引
SELECT * FROM t_user WHERE phone LIKE '%1380';
--优化:倒序字段+反向索引,或ES检索

例 15:前后双 % 通配符 %%

sql

sql 复制代码
--全失效
SELECT * FROM t_user WHERE name LIKE '%三%';
--优化:全文索引FULLTEXT/Elasticsearch

四、联合索引违反最左前缀(3 例:16~18,联合索引 idx_name_status (name,status))

例 16:跳过首字段,直接用第二列查询

sql

sql 复制代码
--失效,缺最左name
SELECT * FROM t_user WHERE status=1;
--优化:补全最左前缀,或单独给status建索引
SELECT * FROM t_user WHERE name!='' AND status=1;

例 17:最左字段做范围查询,后置字段索引失效

sql

sql 复制代码
--name范围>,后面status无法使用索引
SELECT * FROM t_user WHERE name>'张三' AND status=1;
--优化:调整索引顺序(status,name),等值在前范围在后
CREATE INDEX idx_status_name(status,name);

例 18:字段颠倒查询顺序,无最左

sql

sql 复制代码
--失效:先status后name,和索引顺序不一致
SELECT * FROM t_user WHERE status=1 AND name='李四';
--优化:条件顺序不影响优化器,索引顺序不动,无需改SQL,建索引规范即可

五、其他特殊失效场景(2 例:19~20)

例 19:索引选择性过低(字段区分度极差)

sql

sql 复制代码
--status只有0/1两种值,选择性<20%,优化器放弃索引全表扫
SELECT * FROM t_user WHERE status=1;
--优化:小数据无视;大数据按业务分区,不建单字段索引

例 20:MySQL 优化器评估代价后放弃索引(数据量占比过大)

sql

sql 复制代码
--符合条件数据超全表30%,优化器判定全表更快,放弃索引
SELECT * FROM t_user WHERE create_time>'2020-01-01';
--优化:FORCE INDEX强制走索引,或分表归档历史数据
SELECT * FROM t_user FORCE INDEX(idx_ct) WHERE create_time>'2020-01-01';

精简背诵口诀

函数运算隐转换,百分前缀 OR 半边; 不等空值 notin,最左丢了索引残; 选择性低数据多,优化弃索全表翻。

相关推荐
念恒123061 小时前
MySQL事务(上)
数据库·mysql
devilnumber1 小时前
MySQL 执行计划(EXPLAIN)背诵版
数据库·mysql
念恒123061 小时前
MySQL视图
数据库·mysql
骄马之死2 小时前
缓存与数据库一致性的核心方案
mysql·缓存
我叫张小白。2 小时前
基于Redis的缓存架构与一致性保障体系
数据库·redis·缓存·架构
Omics Pro2 小时前
基因泰克:检测级虚拟细胞基准!大语言模型+智能体
大数据·数据库·人工智能·机器学习·语言模型·自然语言处理·r语言
Quincy_Freak2 小时前
工具分享|基于 SQLiteGo 的国产系统离线数据处理方案
大数据·数据库·数据分析·arm·国产系统·银河麒麟·aarch64
我是一颗柠檬2 小时前
【Redis】数据类型详解Day2(2026年)
数据库·redis·后端·缓存
Trouvaille ~2 小时前
【Redis篇】List 列表:双端队列与消息队列的完美实现
数据库·redis·list·双端队列·后端开发·quicklist·zoplist