Ubuntu Java日志中的慢查询优化实战
一 定位与抓取慢查询
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})})
public class SqlExecutionTimeInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
try {
return invocation.proceed();
} finally {
long cost = System.currentTimeMillis() - start;
if (cost > 500) {
StatementHandler sh = (StatementHandler) invocation.getTarget();
BoundSql bs = sh.getBoundSql();
System.out.printf("慢查询预警:SQL执行时间=%dms,SQL=%s%n", cost, bs.getSql());
}
}
}
}
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow.log';
SET GLOBAL log_queries_not_using_indexes = 'ON'; -- 可选:记录未走索引的SQL
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/lib/mysql/mysql-slow.log
long_query_time = 0.5
log_queries_not_using_indexes = ON
pt-query-digest --processlist h=localhost,u=root,p=123456 --limit 10
二 用 Explain 执行计划精准定位瓶颈
CREATE INDEX idx_user_create ON `order`(user_id, create_time);
UPPER(username),在 Java 端先转大写再入参。CREATE INDEX idx_status_age ON user(status, age DESC);
CREATE INDEX idx_user_id ON `order`(user_id);
LIMIT 10000, 20,改用基于主键/索引键的“seek 分页”,如SELECT * FROM user WHERE id > 10000 ORDER BY id LIMIT 20;
SELECT *,以便利用覆盖索引减少回表。三 Java 与数据库配置层面的优化
-Xms 与 -Xmx 一致,启用 G1 GC(-XX:+UseG1GC),按需调节并行/并发 GC 线程数(-XX:ParallelGCThreads、-XX:ConcGCThreads)。-XX:+TieredCompilation),提升热点代码执行效率。ulimit -n)、降低 vm.swappiness、使用 SSD、优化 TCP 参数(如 net.core.somaxconn、net.ipv4.tcp_max_syn_backlog),并监控系统资源(top/htop、vmstat、iostat、dstat)。四 可落地的优化闭环与验证