资讯动态

高德二面:线上慢SQL导致CPU飙升,如何解决?

发布时间:2026/10/22 7:19:00 来源:尧图企业网站定制
很多 Java 同学都有一个疑惑背了几百道八股文刷了一堆面试题可面试依旧频频挂掉不是你知识点记不住而是面试官早就变了考核思路以前面试官可能会问什么是 JVM 内存模型现在更多是场景化连环追问线上 GC 频繁你如何从日志定位到具体代码八股只是基础门槛大厂面试真正考察的是问题排查思路、项目实战经验、技术落地能力。脱离真实业务场景的背诵很容易在面试官连续追问下露馅。✅ 我是枫哥2017 年组建【IT 枫斗者】IT 技术团队深耕 Java 后端面试辅导 8 年。团队导师均来自一线大厂专注帮 IT 从业者夯实技术实力成功入职理想企业。在日常辅导中这类 “背题却不会实战作答” 的案例几乎每天都会遇到。不少同学技术底子尚可但缺少大厂面试的追问视角也没有打磨过项目实战表达。我们提供 1 对 1 学习辅导、大厂面试模拟、企业级项目实战还会为学员定制职业规划全方位提升求职竞争力。8 年间已经帮助数千名求职者拿下满意 Offer。 团队相关IT 枫斗者IT 枫斗者 - Java 面试突击 B 站主页 配套资料点击下载 Java AI Agent 面试题库 RAG MCP 260 题 3 项目源码 Spring AI 实战高德二面线上慢SQL导致CPU飙升如何解决前言这就是典型的慢SQL拖垮整个应用的案例。今天我就带大家从排查、分析到优化完整走一遍线上慢SQL导致CPU飙升的实战处理流程。一、如何快速定位问题当你发现应用或数据库CPU飙升时不要慌按以下步骤快速锁定元凶。1.1 确认数据库层面的CPU消耗登录数据库服务器使用top或htop查看MySQL进程的CPU占用率。如果mysqld的CPU超过100%多核基本可以确定是数据库内部有消耗大的操作。接着进入MySQL命令行执行SHOW PROCESSLIST;重点关注Time执行时间和State状态列。如果出现大量Sending data、Copying to tmp table、Sorting result等状态的会话且执行时间很长大概率就是慢SQL。还可以开启慢查询日志如果没开的话SET GLOBAL slow_query_log1;SET GLOBAL long_query_time1;-- 超过1秒记录然后通过mysqldumpslow工具分析慢日志pt-query-digest /var/log/mysql/slow.log# 或使用mysqldumpslow1.2 拿到具体的SQL从SHOW PROCESSLIST中复制出问题SQL或者从慢日志中提取。例如SELECT o.id, o.amount, u.name, p.title FROM orders o LEFT JOINusersu ON o.user_idu.id LEFT JOIN products p ON o.product_idp.id WHERE o.statusPAIDAND o.create_time2026-01-01ORDER BY o.amount DESC LIMIT1000;二、为什么会慢慢SQL导致CPU飙升的根本原因是数据库需要耗费大量CPU资源去执行全表扫描、排序、创建临时表等操作。2.1 执行计划分析使用EXPLAIN查看SQL的执行计划EXPLAIN SELECT...关键列typeALL表示全表扫描最差range或ref表示用到索引。rows估算扫描行数越大越慢。ExtraUsing filesort文件排序、Using temporary临时表都很耗CPU。2.2 为什么全表扫描会飙高CPUMySQL要逐行读取数据页到内存然后逐行过滤条件。如果表很大千万级即使内存足够也要扫描大量数据CPU忙于解析和比较。排序、分组等操作需要额外内存和CPU计算。2.3 索引失效的常见场景对索引列使用函数WHERE DATE(create_time) 2026-01-01隐式类型转换WHERE user_id 123但user_id是数值类型使用!或LIKE %abc前缀模糊匹配OR 条件中有非索引列三、紧急处理措施止血在找到根本原因之前先要让系统恢复可用避免故障扩大。3.1 杀掉慢查询SHOW PROCESSLIST;-- 找到Id列和执行时间长的会话执行 KILLId;可以写脚本定时kill超过某阈值的SQL。3.2 临时限流在应用层对可疑接口进行限流例如使用Sentinel或Hystrix降低该接口的并发。3.3 重启数据库? 不推荐重启会清空buffer pool可能导致启动后更慢。除非无法连接。四、根治手段优化SQL与索引4.1 添加合适的索引针对上述例子我们分析WHERE o.status PAID AND o.create_time 2026-01-01可以考虑联合索引(status, create_time)。排序字段amount看能否加到索引中避免filesort。优化后ALTER TABLE orders ADD INDEX idx_status_time_amount(status, create_time, amount);再次EXPLAINtype变成rangerows大幅减少Extra不再有Using filesort。4.2 改写SQL避免SELECT *只取必要字段。将LEFT JOIN改为INNER JOIN如果业务允许可提前过滤掉空数据。使用子查询或临时表减少关联数据量。4.3 拆分复杂查询把一条多表JOIN拆成多条简单查询在应用层组装适合数据量不是特别大的场景。五、实战案例原始SQL订单表500万用户表200万商品表100万SELECT o.order_no, u.phone, p.name, o.amount FROM orders o LEFT JOINusersu ON o.user_idu.id LEFT JOIN products p ON o.product_idp.id WHERE o.status1AND o.create_time BETWEEN2026-04-01AND2026-04-30ORDER BY o.amount DESC LIMIT100;问题orders表只有单列索引status导致只过滤了状态但create_time没走索引扫描了全部状态为1的历史订单。ORDER BY amount引发文件排序。优化方案创建联合索引ALTER TABLE orders ADD INDEX idx_status_time_amount(status, create_time, amount);改写SQL将LEFT JOIN改为INNER JOIN因为用户和商品一定有对应数据且不要求展示空。分页优化因为LIMIT 100已经很好。优化后执行计划typerangerows2000Extra中无Using filesort查询时间从30秒下降到0.08秒。效果数据库CPU从85%降到15%应用恢复正常。六、优缺点与适用场景优化手段优点缺点适用场景加索引效果立竿见影增加写入开销占用磁盘高频查询条件选择性好改写SQL不改变数据结构需要业务理解复杂关联、子查询拆分查询应用层组装缓解数据库压力增加网络开销和代码复杂度关联表多但单表数据不大使用缓存大幅降低DB负载一致性难保证读多写少的热点数据读写分离分散读压力主从延迟问题读远大于写七、如何预防慢SQL导致CPU飙升建立SQL审核机制上线前必须通过EXPLAINreview禁止全表扫描语句上线。开启慢查询监控配置阈值如1秒并接入告警系统。定期分析索引使用情况删除未使用的索引优化重复索引。压测大促前对核心查询进行压力测试观察CPU拐点。限流与降级在API网关或业务层配置限流防止突发流量冲击数据库。全链路压测平台提前发现潜在慢SQL。⭐️推荐:Offer训练营介绍Java 面试 后端通用面试八股文Java后端企业级实战面试Java后端校招算法学习

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑