FEATURED · 精选文章

MySQL慢查询根治实战:90%项目索引失效、SQL烂写法,彻底解决线上接口卡顿

发布时间 / 2026/9/11 17:38:30
来源 / 创域科博编辑部
栏目 / 资讯中心
MySQL慢查询根治实战:90%项目索引失效、SQL烂写法,彻底解决线上接口卡顿 后端线上80%的接口卡顿、超时、服务CPU打满问题根本不是代码问题是SQL写得烂、索引用错、隐形失效导致的。很多开发者习惯性建索引就万事大吉结果生产环境高并发、大数据量下索引直接失效、全表扫描横行单条SQL执行几秒甚至几十秒直接拖垮整个服务。更头疼的是本地测试数据量小SQL再烂也秒查一旦上线千万级数据表所有隐性问题全部爆发。今天我们摒弃网上碎片化、老旧的优化口诀结合线上真实故障拆解慢查询排查链路、10大索引失效场景、高危SQL重构方案、生产规范零基础也能快速搞定数据库性能优化。一、先搞懂如何精准抓取线上慢查询优化的前提是找到问题SQL不要凭感觉优化。MySQL自带慢查询日志可精准定位所有拖垮性能的语句。1、开启慢查询日志生产通用配置默认慢日志是关闭状态需要手动开启设置阈值执行超过1秒的SQL全部记录。# 查看慢日志状态 show variables like %slow_query%; # 开启慢查询日志 set global slow_query_log ON; # 慢查询阈值超过1秒即记录 set global long_query_time 1; # 记录未使用索引的SQL set global log_queries_not_using_indexes ON;2、EXPLAIN 分析SQL执行计划抓到慢SQL后第一步不是改代码而是用 EXPLAIN 看执行计划精准定位问题是否走索引、是否全表扫描、索引精度如何。核心关键字段解读生产最关键type执行级别优先级system const eq_ref ref range index ALLALL全表扫描性能最差必须优化key实际命中的索引NULL代表索引失效rows扫描行数数值越大越危险ExtraUsing filesort文件排序、Using temporary临时表都是高危信号二、生产最高频10大索引失效真实场景绝大多数人索引失效不是没建索引而是写法不规范导致索引隐形失效这是线上慢查询的重灾区。1、索引列使用函数运算百分百失效错误原因数据库无法使用函数计算后的索引强制全表扫描。-- 错误索引字段做函数运算 SELECT * FROM user WHERE DATE(create_time) 2026-09-11; -- 正确区间匹配命中索引 SELECT * FROM user WHERE create_time 2026-09-11 00:00:00 AND create_time 2026-09-11 23:59:59;2、隐式类型转换导致索引失效错误原因字段是字符串类型查询用数字MySQL会自动隐式转换索引失效。-- 错误phone为varchar类型传入数字 SELECT * FROM user WHERE phone 13800138000; -- 正确类型严格匹配 SELECT * FROM user WHERE phone 13800138000;3、索引列使用 ! 不等号原理不等号筛选数据离散度高MySQL优化器直接放弃索引走全表扫描。-- 错误不等号导致索引失效 SELECT * FROM order WHERE status ! 0; -- 优化思路业务改写用精准范围替代不等号 SELECT * FROM order WHERE status IN(1,2,3);4、like 左模糊、全模糊查询规则右模糊走索引左模糊、全模糊直接失效。-- 错误左模糊/全模糊索引失效 SELECT * FROM user WHERE name LIKE %张三%; SELECT * FROM user WHERE name LIKE %张三; -- 正确右模糊命中索引 SELECT * FROM user WHERE name LIKE 张三%;5、or 连接无索引字段坑点or 左右字段必须都有索引只要一个无索引整体索引失效。-- 错误phone有索引address无索引整体失效 SELECT * FROM user WHERE phone 13800 OR address 北京; -- 优化拆分语句、union 合并 SELECT * FROM user WHERE phone 13800 UNION SELECT * FROM user WHERE address 北京;6、联合索引不遵循最左匹配原则核心规则联合索引(a,b,c)必须先匹配a跳过a直接查b/c索引完全失效。-- 联合索引idx_user(a,b,c) -- 失效跳过最左a字段 SELECT * FROM user WHERE b 1 AND c 2; -- 生效遵循最左匹配 SELECT * FROM user WHERE a 1 AND c 2;7、not in / not exists 高危写法大数据量表下not in 直接放弃索引全表扫描性能极差严禁用于生产。8、order by、group by 字段无索引排序、分组字段无索引会出现 Using filesort、Using temporary产生临时表、文件排序百万级数据直接卡死。9、参数字段为空导致索引失效业务动态查询中传入空字符串、null会导致索引匹配失效触发全表扫描。10、select * 滥用导致索引覆盖失效查询所有字段无法触发覆盖索引必须回表查询大幅降低性能。三、生产高频慢SQL重构实战1、分页越查越慢问题烂写法offset 超大偏移量数据库需要遍历前面所有数据越往后越慢。-- 烂写法偏移量过大超慢 SELECT * FROM order ORDER BY id DESC LIMIT 10000,10; -- 优化写法主键精准定位分页 SELECT * FROM order WHERE id 10000 ORDER BY id DESC LIMIT 10;2、批量in查询优化in数据量过大时拆分批次查询避免单次检索数据过多导致数据库卡死。3、避免重复统计count(*)count(*)、count(1) 无差别但禁止多条件重复count可使用子查询一次性统计。四、覆盖索引提升性能10倍的终极方案原理索引字段包含查询所需的全部字段无需回表查询直接从索引树拿数据性能拉满。场景高频查询、列表分页、统计接口优先使用覆盖索引。-- 普通索引需要回表 CREATE INDEX idx_phone ON user(phone); -- 覆盖索引直接命中无需回表 CREATE INDEX idx_phone_cover ON user(phone,name,age);EXPLAIN 中 Extra 出现Using index即代表覆盖索引生效。五、生产环境MySQL性能强制规范1、禁止使用 select *按需查询字段优先使用覆盖索引2、禁止索引字段做函数运算、隐式转换、左右模糊匹配3、联合索引严格遵循最左匹配原则高频字段放左侧4、超大分页禁止 offset 偏移查询使用主键分页替代5、严禁 in、not in 超大集合查询必须拆分批次6、排序、分组字段必须建立索引杜绝文件排序和临时表7、定期清理无用索引、重复索引减少写入开销。六、总结MySQL慢查询优化从来不是玄学而是避开失效场景、规范SQL写法、合理设计索引。线上绝大多数数据库卡顿、CPU爆满、接口超时都是开发者不注意细节、滥用烂SQL、建无效索引导致的人为性能事故。掌握慢日志排查、EXPLAIN分析、索引避坑、SQL重构、覆盖索引优化这套完整流程足以应对企业千万级数据表的所有性能问题彻底根治线上数据库瓶颈。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻