当前位置: 代码网 > it编程>编程语言>Java > Mybatis统计sql运行时间的两种方式

Mybatis统计sql运行时间的两种方式

2024年11月04日 Java 我要评论
需求:spring boot + mybatis web项目,统计sql运行时间,用于分析慢sql,优化系统速度。方案有两种:自定义实现 interceptor ,更加灵活。使用现有依赖库(druid

需求:

spring boot + mybatis web项目,统计sql运行时间,用于分析慢sql,优化系统速度。

方案有两种:

  • 自定义实现 interceptor ,更加灵活。
  • 使用现有依赖库(druid):优点是简单好上手,但是统计的只有sql 信息 没有调用参数信息。

一、mybatis 原生拦截器

在 mybatis 中记录 sql 查询的执行时间和 sql 语句,可以使用 mybatis 的拦截器(interceptor)。通过实现自定义拦截器,你可以捕获 sql 执行的开始时间和结束时间,从而计算出执行时间,并将 sql 语句记录到日志中。

  • 自定义拦截器,示例:
import org.apache.ibatis.executor.statement.statementhandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.resulthandler;
import org.apache.ibatis.mapping.boundsql;
import org.apache.ibatis.logging.log;
import org.apache.ibatis.logging.logfactory;

import java.sql.statement;
import java.util.properties;

@intercepts({
    @signature(type = statementhandler.class, method = "query", args = {statement.class, resulthandler.class}),
    @signature(type = statementhandler.class, method = "update", args = {statement.class}),
    @signature(type = statementhandler.class, method = "batch", args = {statement.class})
})
public class sqlexecutioninterceptor implements interceptor {

    private static final log logger = logfactory.getlog(sqlexecutioninterceptor.class);

    @override
    public object intercept(invocation invocation) throws throwable {
        // 获取 sql 语句
        statementhandler statementhandler = (statementhandler) invocation.gettarget();
        boundsql boundsql = statementhandler.getboundsql();
        string sql = boundsql.getsql().replaceall("\\s+", " ").trim();

        // 记录开始时间
        long starttime = system.currenttimemillis();

        // 执行 sql
        object result = invocation.proceed();

        // 计算执行时间
        long endtime = system.currenttimemillis();
        long executiontime = endtime - starttime;

        // 记录 sql 语句和执行时间
        logger.info("sql: " + sql);
        logger.info("execution time: " + executiontime + " ms");

        return result;
    }

    @override
    public object plugin(object target) {
        return plugin.wrap(target, this);
    }

    @override
    public void setproperties(properties properties) {
        // 可以通过配置文件传递参数到拦截器
    }
}

  • 注入bean
@configuration
public class mybatisconfig {
    @bean
    public sqlexecutioninterceptor sqlexecutioninterceptor() {
        return new sqlexecutioninterceptor();
    }
}

备注:可以结合logback等配置将日志打印到单独的日志文件中。

二、使用 druid进行监控

2.1 druid

  • 添加依赖:
<dependency>
    <groupid>com.alibaba</groupid>
    <artifactid>druid</artifactid>
    <version>1.2.8</version> <!-- 使用最新的版本号 -->
</dependency>
  • 配置druid数据源
spring:
  datasource:
    druid:
      url: jdbc:mysql://localhost:3306/your_database
      username: your_username
      password: your_password
      driver-class-name: com.mysql.cj.jdbc.driver
      # 启用druid监控功能
      filters: stat
      # 配置慢sql记录
      maxactive: 20
      initialsize: 1
      minidle: 1
      maxwait: 60000
      # 设置慢查询阈值,单位为毫秒
      slowsqlmillis: 2000
      logslowsql: true
  • 启用druid监控servlet和filter
import com.alibaba.druid.support.http.webstatfilter;
import com.alibaba.druid.support.http.statviewservlet;
import org.springframework.boot.web.servlet.filterregistrationbean;
import org.springframework.boot.web.servlet.servletregistrationbean;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;

@configuration
public class druidconfig {

    // 注册druid的监控servlet
    @bean
    public servletregistrationbean<statviewservlet> druidservlet() {
        servletregistrationbean<statviewservlet> servletregistrationbean = 
                new servletregistrationbean<>(new statviewservlet(), "/druid/*");
        // 设置登录的用户名和密码
        servletregistrationbean.addinitparameter("loginusername", "admin");
        servletregistrationbean.addinitparameter("loginpassword", "admin123");
        return servletregistrationbean;
    }

    // 注册druid的监控过滤器
    @bean
    public filterregistrationbean<webstatfilter> filterregistrationbean() {
        filterregistrationbean<webstatfilter> filterregistrationbean = 
                new filterregistrationbean<>(new webstatfilter());
        // 设置过滤的url模式
        filterregistrationbean.addurlpatterns("/*");
        // 忽略的资源
        filterregistrationbean.addinitparameter("exclusions", "*.js,*.css,/druid/*");
        return filterregistrationbean;
    }
}
  • 访问druid监控页面:启动应用后,可以在浏览器访问 http://localhost:8080/druid(默认端口为8080),登录后查看sql执行情况、慢sql等详细信息。

2.2 druid-spring-boot-starter

就像 spring boot 和 spring,阿里提供了 druid-spring-boot-starter 可以更加方便的基于配置启用相关 filter。

  • 添加依赖:
 <dependency>
    <groupid>com.alibaba</groupid>
    <artifactid>druid-spring-boot-starter</artifactid>
    <version>1.2.8</version>
</dependency>

  • 配置数据源和监控信息
########### 监控配置
# 是否启用statfilter,默认值为false
spring.datasource.druid.web-stat-filter.enabled=true
# 设置监控拦截的url pattern,如果不配置默认所有请求都被拦截
spring.datasource.druid.web-stat-filter.url-pattern=/*
# 设置不拦截的url,多个用英文逗号分隔
spring.datasource.druid.web-stat-filter.exclusions=/druid/*
# 是否开启session统计功能,默认值为true
spring.datasource.druid.web-stat-filter.session-stat-enable=true
# 设置session统计的最大数量,-1表示不限制,默认值为1000
spring.datasource.druid.web-stat-filter.session-stat-max-count=1000
# 设置session统计的principal名称,默认值为“sessionstat”
spring.datasource.druid.web-stat-filter.principal-session-name=sessionstat
# 设置保存session id的cookie名称,默认值为“sessionstatmaxcount”
spring.datasource.druid.web-stat-filter.principal-cookie-name=sessionstatmaxcount
# 是否开启profile,如果开启,需要配置druid监控的filter:profile
spring.datasource.druid.web-stat-filter.profile-enable=true

######### statviewservlet配置
# 是否启用statviewservlet,默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
spring.datasource.druid.stat-view-servlet.enabled=true
# 设置监控页面的访问路径,默认为/druid/*
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 是否允许重置监控数据,默认值为true
spring.datasource.druid.stat-view-servlet.reset-enable=true
# 设置监控页面的登录用户名,默认为空(如果设置了登录用户名和密码,访问监控页面时会弹出登录框)
spring.datasource.druid.stat-view-servlet.login-username=admin
# 设置监控页面的登录密码,默认为空(如果设置了登录用户名和密码,访问监控页面时会弹出登录框)
spring.datasource.druid.stat-view-servlet.login-password=123456
# 设置允许访问监控页面的ip地址列表,多个ip地址之间用英文逗号分隔,默认为空(如果设置了白名单,只有在白名单内的ip地址才能访问监控页面)
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1,192.168.1.1
# 设置禁止访问监控页面的ip地址列表,多个ip地址之间用英文逗号分隔,默认为空(如果设置了黑名单,黑名单内的ip地址不能访问监控页面)
spring.datasource.druid.stat-view-servlet.deny=192.168.1.2

#### 慢sql
# 开启 druid 监控过滤器
spring.datasource.druid.filter.stat.enabled=true
# 是否记录慢 sql 查询
spring.datasource.druid.filter.stat.log-slow-sql=true
# 数据库类型,这里是 mysql
spring.datasource.druid.filter.stat.db-type=mysql
# 定义慢 sql 查询的阈值,单位为毫秒
spring.datasource.druid.filter.stat.slow-sql-millis=1000
  • 日志配置
 <!--   慢sql   -->
    <appender name="slowsqllog" class="ch.qos.logback.core.rolling.rollingfileappender">
        <file>${log.path}/slow_sql-${log.env}.log</file>
        <!--滚动策略,按照时间滚动 timebasedrollingpolicy-->
        <rollingpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedrollingpolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
            <filenamepattern>${log.path}/arch/slow_sql/slow_sql.%d{yyyy-mm-dd}.%i.log.gz</filenamepattern>
            <!-- 单个日志文件最多 100mb -->
            <maxfilesize>100mb</maxfilesize>
            <!--只保留最近10天的日志-->
            <maxhistory>10</maxhistory>
            <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
            <totalsizecap>1gb</totalsizecap>
        </rollingpolicy>
        <!--日志输出编码格式化-->
        <encoder>
            <charset>utf-8</charset>
            <pattern>[%d{yyyy-mm-dd hh:mm:ss}|%mdc{traceid}|] - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.alibaba.druid.filter.stat.statfilter" level="info" additivity="false">
        <appender-ref ref="slowsqllog"/>
    </logger>

以上就是mybatis统计sql运行时间的两种方式的详细内容,更多关于mybatis统计sql运行时间的资料请关注代码网其它相关文章!

(0)

相关文章:

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

发表评论

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