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拆分

相关推荐
云技纵横2 天前
唯一索引 INSERT 死锁实战:5 秒复现交叉插入的 S 锁循环等待
sql·mysql
沉默王二2 天前
面试官:RAG 不用向量数据库,用 MySQL 硬扛?我:100 万向量不是很轻松?
mysql·面试·ai编程
小猿姐3 天前
MySQL Top 10 热点问题 AI 运维实战:从内核诊断到云原生运维
mysql·云原生·aiops
云技纵横3 天前
Gap Lock 死锁实战:5 秒在本地复现 MySQL 间隙锁死锁
后端·mysql
无响应de神3 天前
三、用户与权限管理
数据库·mysql
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
ApacheSeaTunnel4 天前
实战演示 | 基于 Apache SeaTunnel 与 Apache DolphinScheduler 实现 MySQL 到 Doris 离线定时增量同步
大数据·mysql·开源·doris·数据集成·seatunnel·数据同步
DARLING Zero two♡4 天前
【MySQL数据库】数据类型与表约束
数据库·mysql
活宝小娜4 天前
mysql详细安装教程
数据库·mysql·adb