Mysql慢查询日志文件转Excel的方法!
Mysql慢查询日志文件转Excel的方法!
面对公司生产环境中慢SQL问题的排查工作,由于日志文件格式混乱,相关资料无法提供便捷的格式化处理工具,故而自主编写一套Java读取慢SQL日志转为Excel的小工具,该工具可以有效提升排查工作的效率,方便快捷地解决问题。
最近公司生产环境需要排查慢SQL,导出日志txt文件后排查混乱,查找相关资料后并没有找到方便快捷的格式化处理工具,于是自己编写了一套Java读取慢SQL日志转为Excel小工具。
1
2
3
4
5
6
7
8
|
@Data public class SlowQuery { private double queryTime; private double lockTime; private String sqlQuery; private String tableName; private Date executionDate; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
public class MySQLSlowQueryLogParser { // 正则表达式匹配 慢日志内容格式抓取 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(); // 慢查询日志存放路径 String filePath = "D:\日常\2.OA\OASERVERLANDB-slow.log" ; // 导出Excel路径 String excelPath = "D:\日常\2.OA\slow_queries.xlsx" ; // 读取慢查询日志 List<SlowQuery> slowQueries = parser.readSlowQueryLog(filePath); // 写入本地Excel中 parser.writeQueriesToExcel(slowQueries, excelPath); } /** * 读取慢查询日志 返回List对象 * @param filePath 慢查询日志文件路径 * @return List<SlowQuery> 解析结果 * */ public List<SlowQuery> readSlowQueryLog(String filePath) { List<SlowQuery> slowQueries = new ArrayList<>(); // 转流 try (BufferedReader br = new BufferedReader( new FileReader(filePath))) { String line; StringBuilder queryBuilder = new StringBuilder(); // 设定默认值 double queryTime = 0 ; double lockTime = 0 ; boolean isSlowQuery = false ; long timestamp = 0 ; // 用于存储时间戳 while ((line = br.readLine()) != null ) { if (line.startsWith( "# Query_time" )) { // 如果前一个查询存在,添加到列表 if (isSlowQuery) { addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp); } // 解析查询时间和锁定时间 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" )) { // 提取时间戳 Matcher timestampMatcher = TIMESTAMP_PATTERN.matcher(line); if (timestampMatcher.find()) { timestamp = Long.parseLong(timestampMatcher.group( 1 )); // 获取时间戳 } } else if (line.startsWith( "#" ) || line.trim().isEmpty()) { // 忽略注释行和空行 continue ; } else { // 记录当前慢查询的内容 if (isSlowQuery) { queryBuilder.append(line).append( "n" ); } } } // 处理最后一个慢查询 if (queryBuilder.length() > 0 ) { addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp); } } catch (IOException e) { System.out.printf(e.toString()); } return slowQueries; } /** * 添加慢查询对象 * @param slowQueries List<SlowQuery> 慢查询对象集合 * @param queryTime 查询时间 * @param lockTime 锁定时间 * @param sqlQuery Sql执行时间 * @param timestamp 时间戳 * */ 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)); // 设置执行日期 slowQuery.setExecutionDate( new Date(timestamp * 1000 )); slowQueries.add(slowQuery); } /** * 通过Sql语句中 提取出表名 * @param sqlQuery 执行的Sql语句 * @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 "" ; } /** * 通过处理后的集合生成到指定路径 * @param slowQueries 数据集合 * @param filePath 导出的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" ); // 创建标题行 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" ); // 填充数据行 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()); } } |
到此这篇关于Mysql慢查询日志文件转Excel的方法的文章就介绍到这了。
学习资料见知识星球。
以上就是今天要分享的技巧,你学会了吗?若有什么问题,欢迎在下方留言。
快来试试吧,小琥 my21ke007。获取 1000个免费 Excel模板福利!
更多技巧, www.excelbook.cn
欢迎 加入 零售创新 知识星球,知识星球主要以数据分析、报告分享、数据工具讨论为主;
1、价值上万元的专业的PPT报告模板。
2、专业案例分析和解读笔记。
3、实用的Excel、Word、PPT技巧。
4、VIP讨论群,共享资源。
5、优惠的会员商品。
6、一次付费只需129元,即可下载本站文章涉及的文件和软件。
共有 0 条评论