数据库索引失效本质往往是查询语句破坏了B树的查找规则或优化器认为全表扫描更划算。最核心的7种实战失效场景如下附解法1. 违反联合索引最左前缀法则高频大坑联合索引(a, b, c)遵循“最左匹配”。失效SQL跳过前导列如where b1、或前导列使用范围查询如where a1 and b1此时b失效。解法调整索引字段顺序或保证查询条件包含第一个索引列。2. 对索引列进行“隐形包装”函数/计算对列做函数操作或算术运算会让索引树“看不懂”原始值。失效SQLwhere DATE(create_time) 2026-06-26或where age 1 20。解法改为create_time between 2026-06-26 00:00:00 and ...或把计算移到等式右侧。3. 隐式类型转换字符串变数字当字段是varchar类型传入的是数字时MySQL会隐式调用CAST()函数转换。失效SQLwhere phone 13800000000phone为varchar。解法参数加上引号where phone 13800000000。4. 模糊查询以 % 开头B树索引按前缀排序%在开头意味着无法定位起点。失效SQLwhere name like %张三。解法严禁业务使用左模糊若必须用可考虑Elasticsearch等搜索引擎。5. OR 连接导致索引“断片”OR前后的条件必须都建有索引才能生效否则MySQL可能放弃索引走全表。失效SQLwhere nameA or age18假设age无索引。解法拆分成两个SQL用UNION合并或给age也建上索引。6. 负向查询与空值判断NOT / !!、、NOT IN属于范围过大优化器通常判定不走索引。失效SQLwhere status ! 0或where id not in (1,2)。解法业务上尽量用IN或枚举值替代若数据量大且必须查考虑覆盖索引。7. 优化器“嫌弃”索引数据量/统计信息当查询结果超过表的10%~20%或统计信息cardinality陈旧时优化器认为回表成本太高宁愿全表扫描。解法执行analyze table t_name;更新统计信息或强制使用force index慎用。补充避坑范围查询、后的字段在联合索引中也会失效如where a1 and b2 and c3c失效建议将等值查询字段放在联合索引前面。如果遇到具体慢SQL在排查时可以用explain查看key是否为NULL和type是否为ALL/INDEX就能快速定性。针对具体业务建索引的“反三范式”技巧DBA数据库管理员不愿明说的索引设计“黄金法则”。记住这4条你建的索引能扛住高并发而不是“拖油瓶”法则一等值查询排前排范围查询放最后最关键这是对之前“范围导致失效”的降维打击。错误做法联合索引按查询出现的顺序建(age, status, create_time)但查询是where age18 and create_time 2026-01-01 and status1。黄金口诀把和IN的列放在最左边把、、BETWEEN的列挪到最后。正确索引建(age, status, create_time)。因为范围查询后的列在B树里会“断掉”所以必须让它做最后一个字段。法则二区分度高的列“站C位”选择性法则计算区分度公式count(distinct 列) / count(*)结果越接近1越好。大忌给性别男/女建联合索引放在第一位。假如查where sex男 and age20即使索引走(sex,age)因sex区分度极低MySQL扫描完一半数据再过滤age效率甚至不如全表扫描优化器直接放弃索引。正确姿势把age放首位sex放后面。即(age, sex)先通过高区分度age精准定位再回表看性别。法则三覆盖索引——用“空间”换“回表”时间核武器索引里包含了要查询的所有字段就叫“覆盖索引”查询结果直接拿不用回主键查数据性能炸裂。案例订单表查询高频SQL是select order_id, user_id, amount from orders where user_id100。骚操作创建索引(user_id, amount, order_id)把查询的字段塞进索引树。虽然占用存储但查询速度从“毫秒”直接进入“微秒”级这是“反三范式”最值钱的一招。法则四能合并就合并拒绝“冗余索引”建太多索引会让写入INSERT/UPDATE速度暴跌因为每次写都要维护索引树。自查已有索引(a, b)又单独建了(a)。前者完全能覆盖后者后者就是冗余立刻删掉。精简化将多个单列索引a和b合并为联合索引(a, b)前提是查询频率匹配。实战口诀送给你贴工位上等值放前范围后高选列要占排头查询字段塞进去冗余索引赶紧丢。最后提醒没有“万能索引”。建议你把业务中最慢的3条SQL拿出来分别用explain跑一遍按这4条法则硬套立竿见影。explain排查技巧EXPLAIN不是玄学它就是SQL的体检报告。看错指标努力白费。我教你一套“三秒定生死”的排查法只盯4个核心字段第一优先盯死type访问类型—— 性能的“底线”按性能从好到差排列systemconsteq_refrefrangeindexALL。红灯死刑看到ALL全表扫描或index全索引扫描比全表好点有限立刻优化没商量。黄灯及格看到range范围查询如BETWEEN、勉强接受。绿灯优秀看到ref等值匹配或const主键/唯一键查一行说明索引生效了。第二优先死磕Extra额外信息—— 隐藏的“杀手”这里出现特定关键词比typeALL更可怕必杀警告Using filesortMySQL自己悄悄在内存里做文件排序比如ORDER BY没走索引。数据量一大直接卡死必须建联合索引覆盖排序字段。必杀警告Using temporary用了临时表常见于DISTINCT、GROUP BY、UNION。性能极差必须重写SQL或调整索引顺序。大救星Using index这就是我上次说的覆盖索引数据直接从索引树拿不回表性能炸裂看到它请给自己点赞。第三优先看key_len索引长度—— 联合索引“吃了几口”专门对付联合索引(a,b,c)。通过计算长度能判断实际用到了哪几列。技巧key_len值越长说明用到的索引列越多。如果长度只匹配到第一列说明后续列因范围或失效而没吃上这就是排查联合索引失效的铁证。第四优先估算rows扫描行数—— 潜在“风险”它代表优化器预估要扫多少行。每多扫1000行响应时间翻一倍。如果 rows 达到几十万即使typeref也要警惕可能统计信息过时了执行ANALYZE TABLE更新。实战三句口诀贴桌上type看到ALL直接回炉重造。Extra看到filesort或temporary立即加索引。key字段为NULL说明神仙也救不了SQL写错了。特别注意Using index condition是 MySQL 5.6 的索引下推优化这是好事别误判成问题。