Mybatis统计sql运行时间的两种方式
作者:知楠行易
这篇文章主要介绍了Mybatis统计sql运行时间的方案,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运行时间的资料请关注脚本之家其它相关文章!