最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java項(xiàng)目添加慢SQL查詢工具的實(shí)踐指南

 更新時(shí)間:2026年03月01日 09:04:27   作者:有志  
這篇文章主要為大家詳細(xì)介紹了Java項(xiàng)目添加慢SQL查詢工具的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

日期:2026-02-28

場(chǎng)景:校園項(xiàng)目訪問(wèn) Oracle 數(shù)據(jù)庫(kù),部分查詢慢,偶爾出現(xiàn) Hikari 連接池超時(shí),需要定位慢 SQL 并統(tǒng)計(jì)分析。

背景問(wèn)題

項(xiàng)目在高并發(fā)或大數(shù)據(jù)量查詢時(shí),經(jīng)常出現(xiàn):

Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: 
Failed to obtain JDBC Connection; request timed out after 30000ms

初步排查發(fā)現(xiàn):

  • Oracle 數(shù)據(jù)庫(kù)連接池配置較小,慢 SQL 導(dǎo)致連接占用過(guò)久
  • 業(yè)務(wù)查詢中存在 LIKE、GROUP BY、分頁(yè)等操作,大數(shù)據(jù)量下執(zhí)行慢

目標(biāo):快速定位慢 SQL,統(tǒng)計(jì)出現(xiàn)次數(shù)和耗時(shí),便于優(yōu)化。

工具選型

選擇 P6Spy + Logback

  • P6Spy 攔截 JDBC 調(diào)用,透明記錄 SQL
  • 可配置 慢 SQL 閾值(executionThreshold)
  • 性能損耗極小

Spring Boot 配置示例

spring:
  datasource:
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:oracle:thin:@// **********  /orcl
    username: *********
    password: **********************

spy.properties

appender=com.p6spy.engine.spy.appender.Slf4JLogger
executionThreshold=1000      # 超過(guò)1秒才記錄
logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat
resultSetLoggable=false

logback.xml

<appender name="SLOW_SQL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_PATH}/slow-sql.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>${LOG_PATH}/slow-sql-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <maxFileSize>50MB</maxFileSize>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n</pattern>
    </encoder>
</appender>

<logger name="p6spy" level="INFO" additivity="false">
    <appender-ref ref="SLOW_SQL_FILE"/>
</logger>

這樣就可以單獨(dú)輸出慢 SQL 到 slow-sql.log,不干擾 info.log、error.log。

分析思路

慢 SQL 日志樣例:

2026-02-28 17:03:13.617 1772269393616|1073|statement|connection 0|url jdbc:p6spy:oracle:thin:@//...|SELECT COUNT(*) ...

字段說(shuō)明:

字段含義
1073SQL 執(zhí)行耗時(shí)(ms)
statementSQL 類型
connection 0JDBC 連接編號(hào)
SELECT ...實(shí)際執(zhí)行 SQL

分析方法:

  • 找出耗時(shí) > 閾值的 SQL
  • 判斷 SQL 是否包含 LIKE、GROUP BY 或分頁(yè)
  • 統(tǒng)計(jì)出現(xiàn)次數(shù)、最大耗時(shí)、平均耗時(shí)
  • 結(jié)合連接池監(jiān)控判斷是否是連接占用導(dǎo)致超時(shí)

Java 分析工具實(shí)現(xiàn)

可以直接在 Java 環(huán)境運(yùn)行,無(wú)需 Python。

import java.io.*;
import java.util.*;
import java.util.regex.*;

public class SlowSqlAnalyzer {

    public static void main(String[] args) throws IOException {
        if (args.length < 1) {
            System.out.println("Usage: java SlowSqlAnalyzer <slow-sql.log>");
            return;
        }

        String logFile = args[0];

        // 正則匹配 P6Spy SQL 日志行
        Pattern sqlPattern = Pattern.compile("\\|\\d+\\|statement\\|.*?\\|(SELECT|INSERT|UPDATE|DELETE).*", Pattern.CASE_INSENSITIVE);

        Map<String, SqlStats> statsMap = new HashMap<>();

        try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split("\\|", 6);
                if (parts.length < 6) continue;
                int execTime;
                try {
                    execTime = Integer.parseInt(parts[1]);
                } catch (NumberFormatException e) {
                    continue;
                }
                String sqlText = parts[5].trim();
                Matcher matcher = sqlPattern.matcher(line);
                if (matcher.find()) {
                    // 用前200字符作為 key,避免重復(fù)太多
                    String key = sqlText.length() > 200 ? sqlText.substring(0, 200) : sqlText;
                    SqlStats s = statsMap.getOrDefault(key, new SqlStats(sqlText));
                    s.count++;
                    s.totalTime += execTime;
                    s.maxTime = Math.max(s.maxTime, execTime);
                    s.like = s.like || sqlText.toUpperCase().contains("LIKE");
                    s.groupBy = s.groupBy || sqlText.toUpperCase().contains("GROUP BY");
                    statsMap.put(key, s);
                }
            }
        }

        // 輸出統(tǒng)計(jì)結(jié)果
        System.out.printf("%5s | %12s | %12s | %6s | %8s | %s%n",
                "次數(shù)", "平均耗時(shí)(ms)", "最大耗時(shí)(ms)", "LIKE", "GROUP BY", "SQL示例前200字符");
        System.out.println("--------------------------------------------------------------------------------------------------------");

        statsMap.values().stream()
                .sorted((a,b) -> Long.compare(b.totalTime, a.totalTime))
                .forEach(s -> {
                    long avg = s.totalTime / s.count;
                    System.out.printf("%5d | %12d | %12d | %6b | %8b | %s%n",
                            s.count, avg, s.maxTime, s.like, s.groupBy, s.sqlSnippet);
                });
    }

    static class SqlStats {
        String sqlSnippet;
        int count = 0;
        long totalTime = 0;
        long maxTime = 0;
        boolean like = false;
        boolean groupBy = false;

        SqlStats(String sql) {
            this.sqlSnippet = sql;
        }
    }
}

執(zhí)行方法

javac SlowSqlAnalyzer.java
java SlowSqlAnalyzer /data/javaApp/rest-tonp-realization/logs/slow-sql.log

輸出示例:

次數(shù) | 平均耗時(shí)(ms) | 最大耗時(shí)(ms) | LIKE | GROUP BY | SQL示例前200字符
--------------------------------------------------------------------------------------------------------
3    | 1234         | 1567         | true | true     | SELECT ... FROM CERTIFICATION ...
2    | 1050         | 1200         | false| true     | SELECT ... FROM PRODUCT_TYPE_NEW ...

收獲與優(yōu)化建議

可視化慢 SQL

  • 統(tǒng)計(jì)出現(xiàn)次數(shù)、最大耗時(shí)、平均耗時(shí)
  • 可快速定位熱點(diǎn) SQL

SQL 優(yōu)化方向

  • 對(duì)頻繁 LIKE 查詢字段加索引或改寫邏輯
  • 對(duì)大數(shù)據(jù)量 GROUP BY / 分頁(yè)查詢優(yōu)化(索引 + 分批)
  • 避免長(zhǎng)事務(wù)占用連接,結(jié)合 Hikari 連接池配置

整體收益

  • 每條慢 SQL都可被記錄和統(tǒng)計(jì)
  • 高并發(fā)環(huán)境下連接池超時(shí)問(wèn)題更容易排查

總結(jié):

通過(guò) P6Spy + Logback + Java 分析工具,可以快速定位慢 SQL 并統(tǒng)計(jì),為性能優(yōu)化提供數(shù)據(jù)支持。

到此這篇關(guān)于Java項(xiàng)目添加慢SQL查詢工具的實(shí)踐指南的文章就介紹到這了,更多相關(guān)Java添加慢SQL查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot多環(huán)境配置方式的新手教程

    SpringBoot多環(huán)境配置方式的新手教程

    我們平時(shí)做項(xiàng)目的時(shí)候,一般都會(huì)分幾套環(huán)境,每一套環(huán)境的配置都是不一樣的,所以這篇文章就來(lái)為大家詳細(xì)介紹一下SpringBoot多環(huán)境配置方式,希望對(duì)大家有所幫助
    2023-11-11
  • Spring MVC中自帶的跨域問(wèn)題解決方法

    Spring MVC中自帶的跨域問(wèn)題解決方法

    最近做一個(gè)微信小項(xiàng)目遇到一個(gè)跨域問(wèn)題,就是我的前端和后端是放在不同的服務(wù)器上的,然后使用opst請(qǐng)求的時(shí)候報(bào)錯(cuò),所以通過(guò)查找相關(guān)的資料終于解決了,下面這篇文章主要給大家介紹了關(guān)于Spring MVC中自帶的跨域問(wèn)題解決方法的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn)示例

    javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn)示例

    JAXB是Java標(biāo)準(zhǔn)API,用于Java對(duì)象與XML的相互轉(zhuǎn)換,通過(guò)注解定義映射規(guī)則,本文就來(lái)詳細(xì)的介紹一下javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn),感興趣的可以了解一下
    2025-12-12
  • C# log4net使用案例詳解

    C# log4net使用案例詳解

    這篇文章主要介紹了C# log4net使用案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • java使用jacob.jar將word轉(zhuǎn)pdf

    java使用jacob.jar將word轉(zhuǎn)pdf

    這篇文章主要為大家詳細(xì)介紹了java利用jacob.jar將word轉(zhuǎn)pdf,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Java 入門圖形用戶界面設(shè)計(jì)之事件處理上

    Java 入門圖形用戶界面設(shè)計(jì)之事件處理上

    圖形界面(簡(jiǎn)稱GUI)是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。與早期計(jì)算機(jī)使用的命令行界面相比,圖形界面對(duì)于用戶來(lái)說(shuō)在視覺(jué)上更易于接受,本篇精講Java語(yǔ)言中關(guān)于圖形用戶界面的事件處理
    2022-02-02
  • SpringBoot整合EasyExcel實(shí)現(xiàn)復(fù)雜Excel表格的導(dǎo)入導(dǎo)出

    SpringBoot整合EasyExcel實(shí)現(xiàn)復(fù)雜Excel表格的導(dǎo)入導(dǎo)出

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何整合EasyExcel實(shí)現(xiàn)復(fù)雜Excel表格的導(dǎo)入導(dǎo)出功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考下
    2023-11-11
  • 簡(jiǎn)單總結(jié)單例模式的4種寫法

    簡(jiǎn)單總結(jié)單例模式的4種寫法

    今天帶大家學(xué)習(xí)java的相關(guān)知識(shí),文章圍繞著單例模式的4種寫法展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 基于SpringBoot實(shí)現(xiàn)單賬號(hào)登錄控制功能

    基于SpringBoot實(shí)現(xiàn)單賬號(hào)登錄控制功能

    在很多業(yè)務(wù)場(chǎng)景中,我們需要控制單個(gè)賬號(hào)的登錄數(shù)量,本文介紹一種輕量級(jí)實(shí)現(xiàn)方案,靈活支持單賬號(hào)單登錄和多登錄兩種模式,有需要的小伙伴可以了解下
    2025-12-12
  • Spring擴(kuò)展接口知識(shí)總結(jié)

    Spring擴(kuò)展接口知識(shí)總結(jié)

    今天帶大家學(xué)習(xí)Java Spring的相關(guān)知識(shí),文中對(duì)Spring擴(kuò)展接口作了非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05

最新評(píng)論

西城区| 霞浦县| 朝阳县| 平原县| 桑日县| 新化县| 枣庄市| 芮城县| 桂阳县| 宁晋县| 乌兰浩特市| 洛扎县| 钦州市| 华亭县| 克什克腾旗| 周至县| 东城区| 惠东县| 黄平县| 綦江县| 祁东县| 新野县| 原阳县| 红安县| 会昌县| 濉溪县| 丰镇市| 南郑县| 元谋县| 尉氏县| 左云县| 潜山县| 富顺县| 乌鲁木齐县| 木兰县| 文化| 固原市| 丹寨县| 新源县| 大新县| 梧州市|