SpringBoot集成p6spy监控sql耗时

摘要

本文介绍p6spy的使用场景及用法,对于IDE中直接查看sql耗时及拿取完整的sql语句很有帮助,让我们拿下它。

了解p6spy

p6spy是一个开源的JDBC驱动包装器,用于拦截和记录Java应用程序与数据库之间的SQL语句、参数、执行时间等。

作用

  • SQL日志记录:捕获所有SQL语句及其参数,便于调试和验证ORM框架生成的SQL。
  • 性能分析:记录每条SQL的执行耗时,定位慢查询。
  • 慢查询检测:可配置慢查询阈值,自动标记耗时较长的SQL。

注意事项

  • 依赖版本兼容性:确保P6Spy版本与数据库驱动版本兼容(如MySQL 8.x需要 P6Spy 3.9.x)。
  • 若使用MyBatis Plus,需引入mybatis-plus-p6spy依赖。
  • URL格式:数据库连接URL需以jdbc:p6spy:开头(如 jdbc:p6spy:mysql://...)。
  • 配置文件位置:spy.properties文件需放在src/main/resources目录下。
  • 性能开销:P6Spy 会增加少量性能开销(约 5%-10%),生产环境建议关闭或仅开启慢查询监控。

集成步骤

1)引入依赖 pom.xml

xml 复制代码
<!-- sql性能分析插件 -->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.7</version>
</dependency>
<!-- clickhouse -->
<dependency>
    <groupId>com.clickhouse</groupId>
    <artifactId>clickhouse-jdbc</artifactId>
    <version>0.6.5</version>
</dependency>
<dependency>
    <groupId>org.lz4</groupId>
    <artifactId>lz4-java</artifactId>
    <version>1.8.0</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.3.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>

2)可自定义日志解析方式 CustomP6SpyLogger.java

java 复制代码
package org.coffeebeans.p6psy.config;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <li>ClassName: CustomP6SpyLogger </li>
 * <li>Author: OakWang </li>
 */
public class CustomP6SpyLogger implements MessageFormattingStrategy {
    // 匹配日期参数
    private static final Pattern DATE_PATTERN = Pattern.compile("'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{4}'");

    // 使用 ANSI 颜色代码打印不同颜色
    private static final String ANSI_RESET = "\u001B[0m";  //重置颜色
    private static final String ANSI_YELLOW = "\u001B[33m"; //蓝色
    private static final String ANSI_BLUE = "\u001B[34m"; //绿色
    private static final String ANSI_GREEN = "\u001B[32m"; //粉色

    @Override
    public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {
        if (StringUtils.isBlank(sql)) {
            return"";
        }
        // 只处理日期类型的参数
        Matcher matcher = DATE_PATTERN.matcher(sql);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String dateStr = matcher.group();
            dateStr = dateStr.substring(1, dateStr.length() - 1);
            // 替换T为空格,移除时区信息
            String formattedDate = dateStr.replace("T", " ").replaceAll("\+\d{4}$", "");
            matcher.appendReplacement(sb, "'" + formattedDate + "'");
        }
        matcher.appendTail(sb);

        return String.format("%s%s | %s执行时间:%d ms,%s执行SQL:%s%s",
                ANSI_YELLOW, now, ANSI_BLUE, elapsed, ANSI_GREEN, sb, ANSI_RESET);
    }
}

3)定义属性文件 spy.propertis

ini 复制代码
# 定义模块列表,指定MyBatis Plus的日志工厂和P6Spy的中断检测工厂
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory

# 设置日志消息格式类,使用自定义的P6Spy日志记录器
logMessageFormat=org.coffeebeans.p6psy.config.CustomP6SpyLogger
# 或者 自定义日志格式
# logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
# customLogMessageFormat=%(currentTime) | %(executionTime) ms | SQL: %(sqlSingleLine)

# 指定日志追加器,这里使用标准输出日志
appender=com.p6spy.engine.spy.appender.StdoutLogger
# 或者 慢查询日志输出到文件
# appender=com.p6spy.engine.spy.appender.FileLogger
# logfile=logs/p6spy.log
# append=true

# 启用前缀功能,以便在日志条目前添加特定前缀
useprefix=true

# 排除特定类别日志的输出,以减少不必要的日志信息
excludecategories=info,debug,result,commit,resultset
# 排除特定 SQL
exclude=SELECT 1

# 设置日期格式,用于日志条目的时间戳
dateformat=yyyy-MM-dd HH:mm:ss

# 慢查询检测(2秒以上标记为慢查询)
# 启用中断检测功能,以监控数据库操作的中断情况
outagedetection=true
# 设置中断检测间隔,每2秒检查一次数据库操作的中断情况
outagedetectioninterval=2

# 启用过滤功能,根据配置的规则过滤日志输出
filter=true

4)application.yml指定数据库连接驱动及url,以clickhouse为例

yaml 复制代码
# 数据源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    clickhouse:
#      driverClassName: com.clickhouse.jdbc.ClickHouseDriver
#      url: jdbc:clickhouse://192.168.233.129:8123/default
      driverClassName: com.p6spy.engine.spy.P6SpyDriver #使用P6Spy驱动
      url: jdbc:p6spy:clickhouse://192.168.233.129:8123/default  #使用P6Spy的url方式
      username: default
      password: 123456
      initialSize: 10
      maxActive: 100
      minIdle: 10
      maxWait: 6000

5)测试sql打印(省略了集成orm那一套查询细节)

总结

以上我们了解了p6spy的基本作用及使用方式,一般的mybatis/plus打印的sql大概是需要自己拼接的?占位符,这里我们利用第三方工具p6psy就能直接看到sql耗时,且可直接拷贝sql出来运行。

关注公众号:咖啡Beans

在这里,我们专注于软件技术的交流与成长,分享开发心得与笔记,涵盖编程、AI、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。

相关推荐
用户83071968408212 小时前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解13 小时前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解13 小时前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
随风飘的云17 小时前
mysql的innodb引擎对可重复读做了那些优化,可以避免幻读
mysql
洋洋技术笔记17 小时前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者1 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840821 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解2 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者2 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺2 天前
搞懂@Autowired 与@Resuorce
java·spring boot·后端