代码片段:自己动手写SQL慢查询统计

前言

首先,MySQL是有自己的慢查询日志记录的,但是作为开发者,并不一定有权限查看MySQL的日志。因此可以自己动手写个SQL慢查询统计,但这个实现方式所统计到的时间是包含网络开销的,不过在正常情况下,没啥关系,根据统计也能分析到一定原因,主要是这种方式我们能实时监控SQL的大致执行时间,然后有针对的进行SQL优化,能尽快的发现一些问题。

代码实现

  • 切面
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @author itoak
 */
@Aspect
public class SlowQueryMonitorAspect {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private static final Long THRESHOLD = 500L;

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    private Executor executor = Executors.newSingleThreadExecutor();
	
	/**
    * 第一个 * 号表示接口返回类型为任意类型
    * dao后面的 .. 表示dao包以及子包
    * 第二个 * 表示任意接口
    * 第三个 * 表示任意函数名
    * 最后括号内 .. 表示任意参数
    */
    @Pointcut("execution(* cn.itoak.storm.dao..*.*(..))")
    public void monitorPointCut(){}

    @Around("monitorPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String declaringType = joinPoint.getSignature().getDeclaringTypeName();
        long start = System.currentTimeMillis();
        Object object = joinPoint.proceed();
        long end = System.currentTimeMillis() - start;
        if (logger.isInfoEnabled() && end > THRESHOLD) {
            String sql = sqlSessionFactory.getConfiguration().getMappedStatement(declaringType + "." + methodName).getBoundSql(null).getSql();
            logger.info("==> Preparing:{}", sql);
            logger.info("==> Parameters:{}", Arrays.toString(joinPoint.getArgs()));
            logger.info("<== Time consuming:{} ms", end);

            //异步保存到DB,让切面对主流程影响降到最低
            executor.execute(() -> {
                //保存到DB
            });
        }
        return object;
    }
}
  • 配置
import cn.itoak.storm.aspects.SlowQueryMonitorAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @author itoak
 */
@Configuration
@EnableAspectJAutoProxy
public class AspectConfig {
    @Bean
    public SlowQueryMonitorAspect slowQueryMonitorAspect(){
        return new SlowQueryMonitorAspect();
    }
}
  • 结果
c.i.s.aspects.SlowQueryMonitorAspect     : ==> Preparing:select * from z_per where id = ?
c.i.s.aspects.SlowQueryMonitorAspect     : ==> Parameters:[1]
c.i.s.aspects.SlowQueryMonitorAspect     : <== Time consuming:522 ms

注释:代码中THRESHOLD阈值设置的500L ms是为了看到效果,需要自行更改为合适的值。MySQL官方定义慢查询的时间是10S,但是这个时间已经很长了,所以读者根据自己系统的性能要求设置合理的阈值即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值