Mysql慢查詢?nèi)罩疚募D(zhuǎn)Excel的方法
最近公司生產(chǎn)環(huán)境需要排查慢SQL,導(dǎo)出日志txt文件后排查混亂,查找相關(guān)資料后并沒(méi)有找到方便快捷的格式化處理工具,于是自己編寫了一套Java讀取慢SQL日志轉(zhuǎn)為Excel小工具。
@Data
public class SlowQuery {
private double queryTime;
private double lockTime;
private String sqlQuery;
private String tableName;
private Date executionDate;
}public class MySQLSlowQueryLogParser {
// 正則表達(dá)式匹配 慢日志內(nèi)容格式抓取
private static final Pattern QUERY_TIME_PATTERN = Pattern.compile("# Query_time: (\\d+\\.\\d+)");
private static final Pattern LOCK_TIME_PATTERN = Pattern.compile(" Lock_time: (\\d+\\.\\d+)");
private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("SET timestamp=(\\d+);");
public static void main(String[] args) {
MySQLSlowQueryLogParser parser = new MySQLSlowQueryLogParser();
// 慢查詢?nèi)罩敬娣怕窂?
String filePath = "D:\\日常\\2.OA\\OASERVERLANDB-slow.log";
// 導(dǎo)出Excel路徑
String excelPath = "D:\\日常\\2.OA\\slow_queries.xlsx";
// 讀取慢查詢?nèi)罩?
List<SlowQuery> slowQueries = parser.readSlowQueryLog(filePath);
// 寫入本地Excel中
parser.writeQueriesToExcel(slowQueries, excelPath);
}
/**
* 讀取慢查詢?nèi)罩?返回List對(duì)象
* @param filePath 慢查詢?nèi)罩疚募窂?
* @return List<SlowQuery> 解析結(jié)果
* */
public List<SlowQuery> readSlowQueryLog(String filePath) {
List<SlowQuery> slowQueries = new ArrayList<>();
// 轉(zhuǎn)流
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
StringBuilder queryBuilder = new StringBuilder();
// 設(shè)定默認(rèn)值
double queryTime = 0;
double lockTime = 0;
boolean isSlowQuery = false;
long timestamp = 0; // 用于存儲(chǔ)時(shí)間戳
while ((line = br.readLine()) != null) {
if (line.startsWith("# Query_time")) {
// 如果前一個(gè)查詢存在,添加到列表
if (isSlowQuery) {
addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp);
}
// 解析查詢時(shí)間和鎖定時(shí)間
Matcher queryTimeMatcher = QUERY_TIME_PATTERN.matcher(line);
if (queryTimeMatcher.find()) {
queryTime = Double.parseDouble(queryTimeMatcher.group(1));
}
Matcher lockTimeMatcher = LOCK_TIME_PATTERN.matcher(line);
if (lockTimeMatcher.find()) {
lockTime = Double.parseDouble(lockTimeMatcher.group(1));
}
// 開始新的慢查詢
isSlowQuery = true;
// 清空緩存
queryBuilder.setLength(0);
} else if (line.startsWith("SET timestamp")) {
// 提取時(shí)間戳
Matcher timestampMatcher = TIMESTAMP_PATTERN.matcher(line);
if (timestampMatcher.find()) {
timestamp = Long.parseLong(timestampMatcher.group(1)); // 獲取時(shí)間戳
}
} else if (line.startsWith("#") || line.trim().isEmpty()) {
// 忽略注釋行和空行
continue;
} else {
// 記錄當(dāng)前慢查詢的內(nèi)容
if (isSlowQuery) {
queryBuilder.append(line).append("\n");
}
}
}
// 處理最后一個(gè)慢查詢
if (queryBuilder.length() > 0) {
addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp);
}
} catch (IOException e) {
System.out.printf(e.toString());
}
return slowQueries;
}
/**
* 添加慢查詢對(duì)象
* @param slowQueries List<SlowQuery> 慢查詢對(duì)象集合
* @param queryTime 查詢時(shí)間
* @param lockTime 鎖定時(shí)間
* @param sqlQuery Sql執(zhí)行時(shí)間
* @param timestamp 時(shí)間戳
* */
private void addSlowQuery(List<SlowQuery> slowQueries, double queryTime, double lockTime, String sqlQuery, long timestamp) {
SlowQuery slowQuery = new SlowQuery();
slowQuery.setQueryTime(queryTime);
slowQuery.setLockTime(lockTime);
slowQuery.setSqlQuery(sqlQuery);
// 提取表名
slowQuery.setTableName(extractTableName(sqlQuery));
// 設(shè)置執(zhí)行日期
slowQuery.setExecutionDate(new Date(timestamp * 1000));
slowQueries.add(slowQuery);
}
/**
* 通過(guò)Sql語(yǔ)句中 提取出表名
* @param sqlQuery 執(zhí)行的Sql語(yǔ)句
* @return 表名
* */
private String extractTableName(String sqlQuery) {
Pattern pattern = Pattern.compile("FROM\\s+([\\w.]+)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(sqlQuery);
if (matcher.find()) {
return matcher.group(1);
}
return "";
}
/**
* 通過(guò)處理后的集合生成到指定路徑
* @param slowQueries 數(shù)據(jù)集合
* @param filePath 導(dǎo)出的Excel路徑
* */
public void writeQueriesToExcel(List<SlowQuery> slowQueries, String filePath) {
final int MAX_CELL_LENGTH = 32767;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 日期格式化
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Slow Queries");
// 創(chuàng)建標(biāo)題行
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("Query Time (s)");
headerRow.createCell(1).setCellValue("Lock Time (s)");
headerRow.createCell(2).setCellValue("SQL Query");
headerRow.createCell(3).setCellValue("Table Name");
headerRow.createCell(4).setCellValue("Execution Date");
// 填充數(shù)據(jù)行
int rowNum = 1;
for (SlowQuery slowQuery : slowQueries) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(slowQuery.getQueryTime());
row.createCell(1).setCellValue(slowQuery.getLockTime()); // 確保這里寫入的是原始 double 值
String sqlQuery = slowQuery.getSqlQuery();
if (sqlQuery.length() > MAX_CELL_LENGTH) {
sqlQuery = sqlQuery.substring(0, MAX_CELL_LENGTH);
}
row.createCell(2).setCellValue(sqlQuery);
row.createCell(3).setCellValue(slowQuery.getTableName());
row.createCell(4).setCellValue(dateFormat.format(slowQuery.getExecutionDate()));
}
// 寫入到文件
try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
workbook.write(fileOut);
}
} catch (IOException e) {
System.out.printf(e.toString());
}
}到此這篇關(guān)于Mysql慢查詢?nèi)罩疚募D(zhuǎn)Excel的方法的文章就介紹到這了,更多相關(guān)Mysql慢查詢?nèi)罩疚募?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL的指定范圍隨機(jī)數(shù)函數(shù)rand()的使用技巧
這篇文章主要介紹了MySQL的指定范圍隨機(jī)數(shù)函數(shù)rand()的使用技巧,需要的朋友可以參考下2016-09-09
MYSQL中常用的強(qiáng)制性操作(例如強(qiáng)制索引)
對(duì)于經(jīng)常使用oracle的朋友可能知道,oracle的hint功能種類很多,對(duì)于優(yōu)化sql語(yǔ)句提供了很多方法。同樣,在mysql里,也有類似的hint功能。2014-05-05
MySQL雙主搭建+keepalived高可用的實(shí)現(xiàn)
本文主要介紹了MySQL雙主搭建+keepalived高可用的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
關(guān)于MySQL數(shù)據(jù)庫(kù)死鎖的案例和解決方案
MySQL Update語(yǔ)句防止死鎖是指在修改MySQL數(shù)據(jù)庫(kù)的數(shù)據(jù)時(shí),為避免多個(gè)進(jìn)程同時(shí)修改同一數(shù)據(jù)行而造成死鎖的情況,引入了一些機(jī)制來(lái)防止死鎖的產(chǎn)生,本文介紹了一個(gè) MySQL 數(shù)據(jù)庫(kù)死鎖的案例和解決方案,需要的朋友可以參考下2023-09-09
Mysql通過(guò)存儲(chǔ)過(guò)程分割字符串為數(shù)組
今天小編就為大家分享一篇關(guān)于Mysql通過(guò)存儲(chǔ)過(guò)程分割字符串為數(shù)組,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
解決Mysql主從錯(cuò)誤:could not find first log&nbs
這篇文章主要介紹了解決Mysql主從錯(cuò)誤:could not find first log file name in binary問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
MySQL 8.0.20 安裝教程圖文詳解(windows 64位)
這篇文章主要介紹了MySQL 8.0.20安裝教程(windows 64位),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有,需要的朋友可以參考下2020-05-05
Windows版mysql?8.0.28?安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Windows版mysql?8.0.28?安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

