MySQL 索引使用规范:常见失效场景与优化实操方案
一、前言
索引是提升 MySQL 查询速度最直接的手段,但日常开发中很多索引会出现失效问题,即使建立索引,SQL 语句依旧走全表扫描,大表场景下查询耗时成倍增加。
本文整理工作中高频遇到的索引失效场景,附带可复现 SQL 案例与优化写法,规范索引使用习惯,适用于业务表 SQL 优化、慢查询治理场景。
二、索引失效典型场景与优化
查询条件字段参与运算、函数调用
失效案例:
sql
– create_time字段存在索引,使用函数后索引失效
select * from user_info where DATE(create_time) = ‘2026-07-01’;
失效原因:数据库无法使用索引检索函数计算后的结果,会全表遍历。
优化写法:调整条件,让索引字段独立,不参与计算
sql
select * from user_info
where create_time >= ‘2026-07-01 00:00:00’
and create_time < ‘2026-07-02 00:00:00’;字符串字段查询不加引号,隐式类型转换
user_phone 为 varchar 类型且建有索引:
sql
– 错误写法,数字匹配字符串触发隐式转换,索引失效
select * from user_info where user_phone = 13800138000;
– 正确写法,字符串匹配
select * from user_info where user_phone = ‘13800138000’;模糊查询前置百分号 % xx
sql
– 前置%无法走索引
select * from user_info where user_name like ‘%张三’;
– 后置%可以正常使用索引
select * from user_info where user_name like ‘张三%’;
业务需要全模糊匹配时,可考虑全文索引、搜索引擎辅助处理。联合索引不遵循最左匹配原则
建立联合索引 idx_name_age (user_name, age)
sql
– 缺少最左字段user_name,索引失效
select * from user_info where age = 20;
– 遵循最左前缀,正常走索引
select * from user_info where user_name = ‘小明’ and age = 20;使用!=、not in、is not null 等否定条件
这类逻辑会大幅降低索引利用率,数据分布分散时直接放弃索引扫描全表。
优化思路:拆分查询逻辑,改用 in、等值匹配分页查询。
三、索引设计通用规范
区分度低的字段不建索引(如性别、状态只有 0/1 两种值,索引收益极低);
单表索引数量控制在 5 个以内,过多索引会降低新增、更新语句执行速度;
联合索引将高频查询、区分度高的字段放在最左侧;
超长字符串不直接建索引,可截取前缀建立前缀索引;
主键默认自带聚簇索引,避免重复创建主键相关索引。
四、验证索引是否生效的方法
使用 explain 关键字解析 SQL 执行计划,重点观察 type 字段:
type 为 all:全表扫描,未使用索引,需要优化;
type 为 ref/range:正常命中索引,查询效率良好;
key 字段显示实际使用的索引名称,无值代表索引失效。
示例:
sql
explain select * from user_info where user_name = ‘小明’;
五、总结
索引优化是数据库性能调优的基础环节,大部分慢查询根源都是索引使用不当。编码阶段规范 SQL 写法、合理设计索引结构,能大幅减少线上慢 SQL 问题,降低数据库服务器压力。
日常迭代上线前,建议对复杂查询 SQL 执行 explain 校验,提前规避索引失效问题。