MySQL 四大索引失效写法 + 业务替代最优解决方案

核心原则:不是不让你做这个功能,是不让你用「导致索引失效的SQL语法」去做 。 所有模糊、匹配、时间筛选、多值查询都有高性能替代方案,下面逐个对应业务场景给出可直接上线的写法。

目录

[一、左模糊/全模糊查询 LIKE '%xxx' / '%xxx%'](#一、左模糊/全模糊查询 LIKE '%xxx' / '%xxx%')

[1. 为什么不推荐?](#1. 为什么不推荐?)

[2. 业务想实现模糊搜索怎么办?(3种正规方案)](#2. 业务想实现模糊搜索怎么办?(3种正规方案))

[二、字段隐式类型转换(字符串=数字 / 数字=字符串)](#二、字段隐式类型转换(字符串=数字 / 数字=字符串))

[1. 为什么失效?](#1. 为什么失效?)

[2. 正确写法(一秒修复)](#2. 正确写法(一秒修复))

三、索引字段用函数/运算:DATE()、+、-、OR、SUBSTR

[1. 典型烂写法(失效)](#1. 典型烂写法(失效))

[2. 问题本质](#2. 问题本质)

[3. 业务替代最优写法(功能一模一样、索引生效)](#3. 业务替代最优写法(功能一模一样、索引生效))

[四、OR 乱使用 + IN 超大集合](#四、OR 乱使用 + IN 超大集合)

[1. OR 失效解决](#1. OR 失效解决)

[2. IN 超大集合解决(in(1,2,3...10000))](#2. IN 超大集合解决(in(1,2,3...10000)))

五、终极口诀(面试必背、开发必守)


一、左模糊/全模糊查询 LIKE '%xxx' / '%xxx%'

1. 为什么不推荐?

B+树索引是前缀有序,后缀、全文无顺序,无法走索引,直接全表扫描,大表直接超时。

2. 业务想实现模糊搜索怎么办?(3种正规方案)

方案1:能右模糊就全部用右模糊(优先首选)

需求:搜以"华为"开头的商品 正确写法:LIKE '华为%'可以走索引

方案2:必须全模糊/后缀模糊(商品名称、标题搜索)

绝对不要用数据库! 线上标准做法:用 ES / Elasticsearch / Solr 做全文检索,数据库只存原始数据,不扛搜索。

方案3:小表临时兜底

数据量很小(万级以内)可临时用,大表一律上ES。


二、字段隐式类型转换(字符串=数字 / 数字=字符串)

1. 为什么失效?

规则:字段类型被转换,索引失效 例:phone 是字符串索引,你写 where phone=13800001111 MySQL 内部等价于:where CAST(phone AS unsigned)=13800001111 索引字段被函数包裹 → 索引报废。

2. 正确写法(一秒修复)

永远保持两边类型一致

字符串字段 → 加引号:where phone='13800001111'

数字字段 → 不加引号

结论:功能完全不变,但是索引直接生效


三、索引字段用函数/运算:DATE()、+、-、OR、SUBSTR

1. 典型烂写法(失效)

where DATE(create_time) = '2026-05-28'

where user_id + 1 = 1002

2. 问题本质

索引字段被包裹运算 → 无法走B+树有序索引

3. 业务替代最优写法(功能一模一样、索引生效)

时间匹配替代方案(高频)

淘汰:DATE(create_time) = '2026-05-28'

最优:create_time >= '2026-05-28 00:00:00' AND create_time < '2026-05-29 00:00:00'

范围查询替代函数,完美走索引

字段运算替代方案

淘汰:user_id + 1 = 1002

最优:user_id = 1001把运算丢给参数,不丢给字段


四、OR 乱使用 + IN 超大集合

1. OR 失效解决

烂写法:where user_id=1001 or status=1(status无索引)

问题:or 只要有一个无索引字段,整句索引失效

替代方案:拆分 UNION ALL

把两个条件拆成两条单查再合并,各自走各自索引,性能翻倍。

2. IN 超大集合解决(in(1,2,3...10000))

问题:IN 数量过大,MySQL优化器放弃索引走全表扫描

业务解决方案:

1)IN 数量控制在 500~1000 以内

2)超大批量匹配 →临时表/关联JOIN查询

3)批量数据优先走缓存、批量SQL,避免超大IN


五、终极口诀

  1. 字段不动、参数动(永远不对索引字段做函数、运算)

  2. 能右模糊绝不左模糊,全模糊交给ES

  3. 类型严格对齐,杜绝隐式转换

  4. 大IN拆分、烂OR拆分

相关推荐
程序员夏洛6 小时前
MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?
数据库·mysql
l1258657 小时前
# RAG向量数据库优化实战:HNSW索引调参与生产级性能设计
数据库·python·mysql·langchain
梦Arrebol7 小时前
Mysql内容及相关实验
数据库·mysql
OceanWaves19938 小时前
mysql 8.0.32 磁盘爆满,清理从库日志
数据库·mysql
JavaPub-rodert10 小时前
Go 后台如何同时兼容 MySQL、PostgreSQL、SQLite 和 SQL Server?从 ShiyuAdmin 看 GORM 多数据库适配
数据库·mysql·postgresql·golang·javapub·王仕宇
Code额11 小时前
基于 SQLAlchemy 2.x,面向 MySQL 数据库的从入门到精通实战教程(2)
数据库·sql·mysql·adb·ai
爱吃火鸡面呀12 小时前
MySQL 查询与函数详解:从基础条件筛选到高级字符处理
数据库·mysql
知行产研12 小时前
中国矿山无人驾驶出海的三重门
数据库·mysql·php
爱和冰阔落13 小时前
【MySQL 慢查询排查实战】列表接口逐渐变慢时,怎样从请求链路定位原因
android·数据库·mysql
Dxy123931021613 小时前
MySQL有哪些锁?InnoDB锁体系完整梳理博客
数据库·mysql