翼度科技»论坛 编程开发 mysql 查看内容

Mysql慢查询日志文件转Excel

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
最近公司生产环境需要排查慢SQL,导出日志txt文件后排查混乱,查找相关资料后并没有找到方便快捷的格式化处理工具,于是自己编写了一套Java读取慢SQL日志转为Excel小工具。
  1. @Data
  2. public class SlowQuery {
  3.     private double queryTime;
  4.     private double lockTime;
  5.     private String sqlQuery;
  6.     private String tableName;
  7.     private Date executionDate;
  8. }
复制代码
  1. public class MySQLSlowQueryLogParser {
  2.     //  正则表达式匹配 慢日志内容格式抓取
  3.     private static final Pattern QUERY_TIME_PATTERN = Pattern.compile("# Query_time: (\\d+\\.\\d+)");
  4.     private static final Pattern LOCK_TIME_PATTERN = Pattern.compile("  Lock_time: (\\d+\\.\\d+)");
  5.     private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("SET timestamp=(\\d+);");
  6.     public static void main(String[] args) {
  7.         MySQLSlowQueryLogParser parser = new MySQLSlowQueryLogParser();
  8.         //  慢查询日志存放路径
  9.         String filePath = "D:\\日常\\2.OA\\OASERVERLANDB-slow.log";
  10.         //  导出Excel路径
  11.         String excelPath = "D:\\日常\\2.OA\\slow_queries.xlsx";
  12.         //  读取慢查询日志
  13.         List<SlowQuery> slowQueries = parser.readSlowQueryLog(filePath);
  14.         //  写入本地Excel中
  15.         parser.writeQueriesToExcel(slowQueries, excelPath);
  16.     }
  17.     /**
  18.      * 读取慢查询日志 返回List对象
  19.      * @param filePath 慢查询日志文件路径
  20.      * @return List<SlowQuery> 解析结果
  21.      * */
  22.     public List<SlowQuery> readSlowQueryLog(String filePath) {
  23.         List<SlowQuery> slowQueries = new ArrayList<>();
  24.         //  转流
  25.         try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
  26.             String line;
  27.             StringBuilder queryBuilder = new StringBuilder();
  28.             //  设定默认值
  29.             double queryTime = 0;
  30.             double lockTime = 0;
  31.             boolean isSlowQuery = false;
  32.             long timestamp = 0; // 用于存储时间戳
  33.             while ((line = br.readLine()) != null) {
  34.                 if (line.startsWith("# Query_time")) {
  35.                     // 如果前一个查询存在,添加到列表
  36.                     if (isSlowQuery) {
  37.                         addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp);
  38.                     }
  39.                     // 解析查询时间和锁定时间
  40.                     Matcher queryTimeMatcher = QUERY_TIME_PATTERN.matcher(line);
  41.                     if (queryTimeMatcher.find()) {
  42.                         queryTime = Double.parseDouble(queryTimeMatcher.group(1));
  43.                     }
  44.                     Matcher lockTimeMatcher = LOCK_TIME_PATTERN.matcher(line);
  45.                     if (lockTimeMatcher.find()) {
  46.                         lockTime = Double.parseDouble(lockTimeMatcher.group(1));
  47.                     }
  48.                     // 开始新的慢查询
  49.                     isSlowQuery = true;
  50.                     // 清空缓存
  51.                     queryBuilder.setLength(0);
  52.                 } else if (line.startsWith("SET timestamp")) {
  53.                     // 提取时间戳
  54.                     Matcher timestampMatcher = TIMESTAMP_PATTERN.matcher(line);
  55.                     if (timestampMatcher.find()) {
  56.                         timestamp = Long.parseLong(timestampMatcher.group(1)); // 获取时间戳
  57.                     }
  58.                 } else if (line.startsWith("#") || line.trim().isEmpty()) {
  59.                     // 忽略注释行和空行
  60.                     continue;
  61.                 } else {
  62.                     // 记录当前慢查询的内容
  63.                     if (isSlowQuery) {
  64.                         queryBuilder.append(line).append("\n");
  65.                     }
  66.                 }
  67.             }
  68.             // 处理最后一个慢查询
  69.             if (queryBuilder.length() > 0) {
  70.                 addSlowQuery(slowQueries, queryTime, lockTime, queryBuilder.toString().trim(), timestamp);
  71.             }
  72.         } catch (IOException e) {
  73.             System.out.printf(e.toString());
  74.         }
  75.         return slowQueries;
  76.     }
  77.     /**
  78.      * 添加慢查询对象
  79.      * @param slowQueries List<SlowQuery> 慢查询对象集合
  80.      * @param queryTime 查询时间
  81.      * @param lockTime 锁定时间
  82.      * @param sqlQuery Sql执行时间
  83.      * @param timestamp 时间戳
  84.      * */
  85.     private void addSlowQuery(List<SlowQuery> slowQueries, double queryTime, double lockTime, String sqlQuery, long timestamp) {
  86.         SlowQuery slowQuery = new SlowQuery();
  87.         slowQuery.setQueryTime(queryTime);
  88.         slowQuery.setLockTime(lockTime);
  89.         slowQuery.setSqlQuery(sqlQuery);
  90.         // 提取表名
  91.         slowQuery.setTableName(extractTableName(sqlQuery));
  92.         // 设置执行日期
  93.         slowQuery.setExecutionDate(new Date(timestamp * 1000));
  94.         slowQueries.add(slowQuery);
  95.     }
  96.     /**
  97.      * 通过Sql语句中 提取出表名
  98.      * @param sqlQuery 执行的Sql语句
  99.      * @return 表名
  100.      * */
  101.     private String extractTableName(String sqlQuery) {
  102.         Pattern pattern = Pattern.compile("FROM\\s+([\\w.]+)", Pattern.CASE_INSENSITIVE);
  103.         Matcher matcher = pattern.matcher(sqlQuery);
  104.         if (matcher.find()) {
  105.             return matcher.group(1);
  106.         }
  107.         return "";
  108.     }
  109.     /**
  110.      * 通过处理后的集合生成到指定路径
  111.      * @param slowQueries 数据集合
  112.      * @param filePath 导出的Excel路径
  113.      * */
  114.     public void writeQueriesToExcel(List<SlowQuery> slowQueries, String filePath) {
  115.         final int MAX_CELL_LENGTH = 32767;
  116.         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 日期格式化
  117.         try (Workbook workbook = new XSSFWorkbook()) {
  118.             Sheet sheet = workbook.createSheet("Slow Queries");
  119.             // 创建标题行
  120.             Row headerRow = sheet.createRow(0);
  121.             headerRow.createCell(0).setCellValue("Query Time (s)");
  122.             headerRow.createCell(1).setCellValue("Lock Time (s)");
  123.             headerRow.createCell(2).setCellValue("SQL Query");
  124.             headerRow.createCell(3).setCellValue("Table Name");
  125.             headerRow.createCell(4).setCellValue("Execution Date");
  126.             // 填充数据行
  127.             int rowNum = 1;
  128.             for (SlowQuery slowQuery : slowQueries) {
  129.                 Row row = sheet.createRow(rowNum++);
  130.                 row.createCell(0).setCellValue(slowQuery.getQueryTime());
  131.                 row.createCell(1).setCellValue(slowQuery.getLockTime()); // 确保这里写入的是原始 double 值
  132.                 String sqlQuery = slowQuery.getSqlQuery();
  133.                 if (sqlQuery.length() > MAX_CELL_LENGTH) {
  134.                     sqlQuery = sqlQuery.substring(0, MAX_CELL_LENGTH);
  135.                 }
  136.                 row.createCell(2).setCellValue(sqlQuery);
  137.                 row.createCell(3).setCellValue(slowQuery.getTableName());
  138.                 row.createCell(4).setCellValue(dateFormat.format(slowQuery.getExecutionDate()));
  139.             }
  140.             // 写入到文件
  141.             try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
  142.                 workbook.write(fileOut);
  143.             }
  144.         } catch (IOException e) {
  145.             System.out.printf(e.toString());
  146.         }
  147.     }
复制代码
来源:https://www.cnblogs.com/shangjianan/p/18517599
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具