MySQL索引失效场景详解:程序员必知的10大索引失效原因及优化方案。本文深入解析MySQL索引失效的常见情况,包括函数操作、模糊查询、最左前缀原则、OR条件、隐式转换等,帮助开发者避免性能陷阱。掌握这些MySQL索引优化技巧,提升数据库查询效率,轻松应对面试中的索引相关问题。了解索引失效原理,写出高性能SQL语句,让你的应用飞起来!
好的,请看这篇以程序员角度撰写的SEO优化软文:
大家好,咱们程序员在面试数据库相关岗位,尤其是后端开发时,MySQL索引绝对是绕不开的重点知识。面试官特别爱问的就是:“什么情况下索引会失效啊?” 这个问题看似简单,但回答不全面或者踩了坑,很可能就与Offer失之交臂了。今天就来详细聊聊那些常见的MySQL索引失效场景,帮你面试时稳稳拿下这道题!
这是非常经典的一个坑!比如你有个用户表,birthday 是日期类型的列并且建了索引。你要查年龄大于30的人,如果写成 WHERE YEAR(CURDATE()) - YEAR(birthday) > 30,那完蛋了,索引大概率失效。数据库计算表达式的时候,是用不到索引的。正确姿势是直接比较日期:WHERE birthday < DATE_SUB(CURDATE(), INTERVAL 30 YEAR)。
关键词:索引失效, MySQL索引
跟上一条类似,但更常见的是直接对列做加减乘除。假设有个订单表,amount(金额)有索引。你写 WHERE amount * 0.9 > 1000 想查打了9折后大于1000的订单?抱歉,数据库只能老老实实扫描全表计算每个 amount * 0.9,索引用不上。应该把计算移到右边:WHERE amount > 1000 / 0.9。
关键词:索引失效场景
LIKE '%xxx')模糊查询中,LIKE 'abc%' 这种右模糊或者 LIKE 'abc' 是可以用上索引的(如果是前缀索引或合适的数据类型)。但如果写成 LIKE '%abc' 或者 LIKE '%abc%'(左模糊或全模糊),数据库引擎就不知道从哪里开始匹配了,索引通常就失效了。想象一下,让你在字典里找一个以特定几个字母 结尾 的单词,你怎么快速找?得从头翻吧!同理,数据库面对左模糊也得全表扫。所以尽量避免左模糊,如果实在需要,考虑其他方案如全文索引。
关键词:MySQL索引失效, 索引失效
这个原则是针对组合索引(也叫联合索引、复合索引)的命门!组合索引 (col1, col2, col3) 是按照 col1, col2, col3 的顺序建立索引树的。数据库想用这个索引,查询条件必须从索引的最左边列开始并且连续(中间不能跳过)。
WHERE col1 = ? (用到了 col1)WHERE col1 = ? AND col2 = ? (用到了 col1, col2)WHERE col1 = ? AND col2 = ? AND col3 = ? (用到了 col1, col2, col3)WHERE col1 = ? AND col3 = ? (部分索引下推,能用上 col1 的索引部分,但 col3 可能不会用来过滤,效率不如用上 col2)WHERE col2 = ? (最左列 col1 没出现)WHERE col2 = ? AND col3 = ? (最左列 col1 没出现)WHERE col1 = ? AND col3 = ? (跳过了中间的 col2。虽然能用上 col1,但索引的效率会打折扣,有时优化器可能干脆选择全表扫)设计组合索引和写 SQL 时,脑子里一定要有这个原则!
关键词:索引失效场景, MySQL索引失效, 最左前缀原则
当 WHERE 子句中出现 OR 条件时,情况比较复杂。如果 OR 连接的列中存在至少一个列没有索引,那么整个查询可能就无法有效使用索引,导致全表扫描。例如:WHERE indexed_col = 'value' OR non_indexed_col = 'value'。优化策略通常是把 OR 拆成 UNION ALL(要注意去重问题)或者重新设计表结构给 non_indexed_col 加索引。
数据库在比较时如果发现两边的数据类型不一致,会尝试进行隐式转换。比如索引列 phone 是 varchar 类型存储手机号,你写 WHERE phone = 13800138000(用了数字),数据库会把 phone 列的值都转成数字来比较,这就导致索引失效。正确的写法应该是 WHERE phone = '13800138000',保证类型匹配。这个小细节很容易忽略!
关键词:索引失效, MySQL索引失效场景
有时,即使有索引可用,查询优化器经过成本计算后,可能会认为扫描全表反而比走索引再回表更快。这种情况通常发生在:
SELECT * FROM table LIMIT 1000000, 10 (获取大量数据偏移后的少量数据),索引扫描+大量回表的代价可能高于直接顺序扫描全表。所以,索引不是万能的,优化器的选择是动态的。
关键词:索引失效, MySQL索引失效场景, 查询优化器
NOT、NOT IN、NOT LIKE、!= 或 <> 操作符这些否定操作符通常难以高效利用索引。数据库很难在索引中快速定位到“不等于某个值”的所有记录,往往需要扫描大部分索引或全表。例如 WHERE status != 'active',如果 status 索引,优化器可能还是会选择全扫。对于 NOT IN 和 NOT EXISTS,如果子查询结果集很大,效率也会很低。尽量用正向条件或考虑其他方案(如 LEFT JOIN ... IS NULL 代替 NOT IN)。
关键词:索引失效场景, MySQL索引
IS NULL 或 IS NOT NULL在较早版本的 MySQL 或特定情况下,WHERE indexed_col IS NULL 可能用不到索引,需要全表扫描。但在较新版本(如 5.6+)且索引列允许为 NULL 的情况下,优化器通常能够利用索引来查找 IS NULL 的记录。不过,IS NOT NULL 依然可能导致索引失效,因为它通常意味着需要扫描索引中大量的非 NULL 值(除非 NULL 值占比很高)。具体情况最好用 EXPLAIN 查看执行计划确认。
在组合索引中,如果某一列使用了范围查询(>, <, BETWEEN, LIKE 'prefix%' 等),那么该列之后的索引列将无法再用于索引过滤。例如索引 (col1, col2, col3),查询 WHERE col1 = 'a' AND col2 > 10 AND col3 = 'b'。数据库能用索引快速定位到 col1='a' 并且 col2>10 的记录,但对于 col3='b' 这个条件,由于 col2 用了范围查询,col3 在索引中是乱序的,无法高效利用索引进行等值匹配,只能回表后再过滤 col3。设计索引顺序时,尽量把等值查询的列放在范围查询列的前面。
关键词:MySQL索引失效, 组合索引, 索引失效
写在最后:
理解这些MySQL索引失效的场景,不仅仅是应付面试,对于日常开发写出高性能的SQL至关重要。面试前多想想这些点,回答时结合具体例子,面试官一定会对你刮目相看!
对了,如果大家需要购买面试鸭会员,可以通过 面试鸭返利网 (mianshiyafanli.com) 找到我,返利25元!能省一点是一点嘛。

最后送个福利!2025年Java面试宝典: 链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g 提取码: 9b3g
希望这篇文章能帮助大家在面试路上少踩坑,早日拿下心仪的Offer!
扫码联系我返利
(当前返利8元,金额随官方实际价格波动,最好提前咨询)

面试鸭小程序码

美团大额优惠券,给自己加个鸡腿吧!

支付宝扫码领取1-8元无门槛红包
