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、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。

相关推荐
知其然亦知其所以然3 小时前
MySQL 社招必考题:如何优化WHERE子句?
后端·mysql·面试
编啊编程啊程3 小时前
Netty从0到1系列之RPC通信
java·spring boot·rpc·kafka·dubbo·nio
王大锤43913 小时前
2种方式从springbean中获取bean实例
java·spring boot
mumu1307梦3 小时前
SpringAI 实战:解决 Netty 超时问题,优化 OpenAiApi 配置
java·spring boot·netty·超时·timeout·openapi·springai
咖啡Beans3 小时前
了解Mybatis拦截器
java·spring boot·mybatis
DemonAvenger4 小时前
MySQL性能优化案例分析:从问题到解决方案
数据库·mysql·性能优化
Q_Q5110082854 小时前
python+django/flask哈利波特书影音互动科普网站
spring boot·python·django·flask·node.js·php
杨云龙UP4 小时前
20250922_(Linux操作系统上)Oracle、MySQL、MariaDB、SQL Server常用连接命令与基础查询
mysql·oracle·sqlserver·mariadb
九转苍翎4 小时前
Java外功基础(1)——Spring Web MVC
spring boot