MySQL索引失效是数据库性能优化的关键问题,本文深度解析8大高频索引失效场景,包括违反最左前缀原则、隐式类型转换、OR条件不当使用等核心知识点。通过分析B+树索引原理,揭示索引失效的本质原因,并提供EXPLAIN命令、覆盖索引等实用优化方案。掌握这些MySQL索引优化技巧,能有效提升SQL查询性能,避免全表扫描。无论是Java面试准备还是实际开发,这些索引失效案例分析和解决方案都能帮助你构建高性能数据库应用。学习如何正确处理模糊查询、函数运算等易错场景,让你的SQL语句充分利用索引优势。
2025年Java面试宝典:
链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g
提取码: 9b3g
索引失效的本质是查询条件无法有效利用B+树的有序性。当SQL语句的编写方式导致无法通过索引快速定位数据时,就会触发全表扫描。理解这一点,就能更好地分析具体的失效场景。
典型场景:
CREATE INDEX idx_name_age ON user(name, age);
SELECT * FROM user WHERE age = 25; -- 失效
失效原因:
复合索引的存储结构决定了必须按照索引字段顺序匹配。跳过第一个字段name
直接查询age
时,B+树的有序性被破坏,无法快速定位。
延伸考点:
WHERE name='张三' AND age>20
(有效)WHERE age=25 AND name='张三'
(有效,优化器自动调整顺序)典型场景:
SELECT * FROM orders WHERE YEAR(create_time) = 2023; -- 失效
失效原因:
对索引列使用函数后,数据库需要逐行计算函数结果,无法直接使用索引的有序性。应改为范围查询:
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
典型场景:
CREATE INDEX idx_phone ON user(phone); -- phone是varchar类型
SELECT * FROM user WHERE phone = 13800138000; -- 失效
失效原因:
将字符串类型的phone
与数字比较时,MySQL会隐式转换所有phone
值为数字,等价于对索引列使用函数。
典型场景:
CREATE INDEX idx_age ON user(age);
SELECT * FROM user WHERE age=25 OR salary>10000; -- 失效
失效原因:
OR连接的两个条件中,只要有一个字段没有索引,就会触发全表扫描。建议改用UNION:
SELECT * FROM user WHERE age=25
UNION
SELECT * FROM user WHERE salary>10000;
典型场景:
CREATE INDEX idx_name ON user(name);
SELECT * FROM user WHERE name LIKE '%张%'; -- 可能失效
失效原因:
前导通配符%
导致无法利用索引的有序性。但LIKE '张%'
(无前导%)可以使用索引。
典型场景:
CREATE INDEX idx_gender ON user(gender); -- gender只有'男'/'女'两种值
SELECT * FROM user WHERE gender='男'; -- 可能失效
失效原因:
当索引列的唯一值过少时(例如性别),数据库可能认为全表扫描比索引查询更快。
典型场景:
CREATE INDEX idx_age ON user(age);
SELECT * FROM user WHERE age != 25; -- 失效
失效原因:
不等于操作需要扫描所有不满足条件的记录,无法有效利用索引的有序性。
典型场景:
CREATE INDEX idx_age ON user(age);
SELECT * FROM user WHERE age IS NULL; -- 可能失效
失效原因:
当表中大部分记录都满足IS NULL
条件时,优化器可能选择全表扫描。
type
字段(至少达到range
级别)SELECT
具体字段减少回表操作扫码联系我返利
(当前返利8元,金额随官方实际价格波动,最好提前咨询)
面试鸭小程序码
美团大额优惠券,给自己加个鸡腿吧!