当前位置: 代码网 > it编程>编程语言>Java > Java慢查询排查与性能调优完整实战指南

Java慢查询排查与性能调优完整实战指南

2025年08月09日 Java 我要评论
1. 事故全景:从告警到定位1.1 事故时间线timeline title 故障时间轴 00:00 : 监控系统首次告警 00:05 : 数据库连接池使用率突破90% 00:0

1. 事故全景:从告警到定位

1.1 事故时间线

timeline
    title 故障时间轴
    00:00 : 监控系统首次告警
    00:05 : 数据库连接池使用率突破90%
    00:08 : 网关开始出现503错误
    00:12 : 自动扩容触发
    00:15 : 人工介入排查

1.2 关键指标异常

指标正常值故障值超出阈值
接口p99响应时间200ms
数据库qps8003500
活跃连接数20200(max)10x

1.3 排查工具链

// 监控工具清单
public class troubleshootingtools {
    string[] tools = {
        "skywalking 8.7.0", 
        "arthas 3.6.7",
        "prometheus + grafana",
        "mysql slow query log"
    };
}

2. 深度剖析:mysql 分页查询的致命陷阱

2.1 offset 分页的执行原理

​​性能消耗公式​​

总成本 = 全表扫描成本 + 排序成本 + 跳过行成本

2.2 索引失效的根本原因

-- 问题sql示例
explain select * from member_info 
where status = 1 
order by create_time desc 
limit 10000, 20;

​​执行计划关键解读​​:

  • type: all:全表扫描
  • rows: 1250000:扫描行数
  • extra: using filesort:无法利用索引排序

2.3 深度优化方案对比

方案一:游标分页(推荐)

-- 优化后sql(基于id分页)
select * from member_info 
where status = 1 and id > #{lastid}
order by id asc 
limit 20;

方案二:覆盖索引优化

-- 新增复合索引
alter table member_info 
add index idx_status_createtime (status, create_time);

-- 改写sql
select * from member_info 
where status = 1 
order by create_time desc 
limit 20;

方案对比表

方案扫描行数排序方式适用场景
原始offset10020文件排序小数据量
游标分页20索引排序大数据量、深度分页
覆盖索引20索引覆盖中等数据量

3. 完整优化实战

3.1 mybatis 改造示例

public interface membermapper {
    // 旧方法(问题代码)
    @select("select * from member_info where status = #{status} limit #{offset}, #{limit}")
    list<member> listbypage(@param("status") int status, 
                          @param("offset") int offset,
                          @param("limit") int limit);

    // 新方法(优化后)
    @select("select * from member_info where status = #{status} and id > #{lastid} order by id asc limit #{limit}")
    list<member> listbycursor(@param("status") int status,
                            @param("lastid") long lastid,
                            @param("limit") int limit);
}

3.2 服务层改造

public pageresult<member> getmemberlist(int pagesize, long lastid) {
    // 游标分页查询
    list<member> members = membermapper.listbycursor(1, lastid, pagesize);
    
    // 获取下一页的游标
    long nextlastid = members.isempty() ? null : members.get(members.size()-1).getid();
    
    return new pageresult<>(members, nextlastid);
}

4. 防御体系:慢查询防控全景方案

4.1 事前预防

4.2 事中监控

# my.cnf 慢查询配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

5. 优化效果验证

5.1 压测数据对比

场景tps平均响应时间错误率cpu使用率
优化前856100ms32%96%
优化后2150230ms0%45%

6. 工程师的自我修养

6.1 sql 编写军规

  1. ​​禁止​​ 无限制的 select * ​​
  2. 必须​​ 为分页查询添加 order by ​​
  3. 推荐​​ 使用游标替代 offset
  4. ​​强制​​ 为 where 条件字段建立索引

总结

到此这篇关于java慢查询排查与性能调优的文章就介绍到这了,更多相关java慢查询排查与性能调优内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com