当前位置: 首页 > news >正文

Python实现Java mybatis-plus 产生的SQL自动化测试SQL速度和判断SQL是否走索引

Python实现Java mybatis-plus 产生的SQL自动化测试SQL速度和判断SQL是否走索引

文件目录如下

│  sql_speed_test.py
│  
├─input
│      data-report_in_visit_20240704.log
│      resource_in_sso_20240704.log
│      
└─outputdata-report_in_visit_20240704.csvresource_in_sso_20240704.csv

目前每次做实验都要将Java中的SQL做性能测试,否则就没法通过考核,属实难崩。

sql_speed_test.py是我用python写的程序,将从Java mybatis-plus控制台产生的日志复制到data-report_in_visit_20240704.logresource_in_sso_20240704.log文件中,运行程序之后output文件夹会自动输出csv文件,下面为csv文件夹详情。

data-report_in_visit_20240704.log文件

-- 301 -- [2024-07-04 14:22:55.055] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger] [http-nio-9006-exec-2] [143] [DEBUG] [traceId:] ==>
SELECT resource_id AS resource_id, resource_type AS resource_type, sum(IFNULL(internal_pv, pv)) AS internal_pv, sum(IFNULL(google_pv, pv)) AS google_pv, sum(IFNULL(other_pv, pv)) AS other_pv, sum(IFNULL(pv, 0)) AS pv FROM t_bw_article_daily_statistic where resource_type = 9 GROUP BY resource_id, resource_type order by resource_id, resource_type
-- 302 -- [2024-07-04 14:22:55.055] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger] [http-nio-9006-exec-2] [143] [DEBUG] [traceId:] ==>
SELECT resource_id AS resource_id, resource_type AS resource_type, sum(IFNULL(internal_pv, pv)) AS internal_pv, sum(IFNULL(google_pv, pv)) AS google_pv, sum(IFNULL(other_pv, pv)) AS other_pv, sum(IFNULL(pv, 0)) AS pv FROM t_bw_article_daily_statistic_202406 where resource_type = 9 GROUP BY resource_id, resource_type order by resource_id, resource_type

data-report_in_visit_20240704.csv文件

序号SQL功能描述SQL预估业务数据量实际测试数据量执行时间执行结果索引是否生效所属项目所在库
1SELECT resource_id AS resource_id, resource_type AS resource_type, sum(IFNULL(internal_pv, pv)) AS internal_pv, sum(IFNULL(google_pv, pv)) AS google_pv, sum(IFNULL(other_pv, pv)) AS other_pv, sum(IFNULL(pv, 0)) AS pv FROM t_bw_article_daily_statistic where resource_type = 9 GROUP BY resource_id, resource_type order by resource_id, resource_typet_bw_article_daily_statistict_bw_article_daily_statistic:5741行0.419603 秒462data-reportvisit
2SELECT resource_id AS resource_id, resource_type AS resource_type, sum(IFNULL(internal_pv, pv)) AS internal_pv, sum(IFNULL(google_pv, pv)) AS google_pv, sum(IFNULL(other_pv, pv)) AS other_pv, sum(IFNULL(pv, 0)) AS pv FROM t_bw_article_daily_statistic_202406 where resource_type = 9 GROUP BY resource_id, resource_type order by resource_id, resource_typet_bw_article_daily_statistic_202406t_bw_article_daily_statistic_202406:296358行0.291532 秒2691data-reportvisit

sql_speed_test.py文件

import os
import csv
import re
from pymysql import *
import time"""
开发一个用于SQL性能测试的工具,避免一直做重复工作
将Java中的每一条SQL采用mybatis-plus-plugin插件抓出来转存至log文件中
抓住每条SQL做测试
"""def extract_query_sql_table_names(sql):# 正则表达式模式pattern = re.compile(r"\b(?:FROM|JOIN|INTO|UPDATE|TABLE|INTO)\s+([`\"\[\]]?[a-zA-Z_][\w$]*[`\"\[\]]?)",re.IGNORECASE)# 查找所有匹配的表名matches = pattern.findall(sql)# 去掉引号和方括号tables = [re.sub(r'[`"\[\]]', '', match) for match in matches]filter_tables = []for table in tables:if "t_bw" in table:filter_tables.append(table)return filter_tablesdef check_index_usage(connection, sql):if not sql.startswith("select") and not sql.startswith("SELECT"):return Falsetry:with connection.cursor() as cursor:# 使用 EXPLAIN 来获取查询计划explain_sql = f"EXPLAIN {sql}"cursor.execute(explain_sql)explain_result = cursor.fetchall()# 打印 EXPLAIN 结果print("EXPLAIN 结果:")for row in explain_result:print(row)# 检查每行是否使用了索引for row in explain_result:if row[5] is not None:print(f"SQL 使用了索引: {row[5]}")return Trueprint("SQL 未使用索引")return Falsefinally:pass# connection.close()def count_rows(connection, table_name):try:with connection.cursor() as cursor:# 构建 SQL 语句sql = f"SELECT COUNT(*) FROM {table_name}"# 执行 SQL 语句cursor.execute(sql)# 获取结果result = cursor.fetchone()# 返回结果return result[0]except Exception as e:print(e)finally:# connection.close()passclass SqlSpeedTest:def __init__(self):self.input_dir = "./input"self.output_dir = "./output"self.databases = {"sso": {"ip": "xxxxxx","database": "sso","username": "xxxx","password": "xxxx"}}def get_all_input_files(self):files = os.listdir(r'./input')# file_paths = []# for file in files:#     file_paths.append(self.input_dir + "/" + file)return filesdef handle_sql_log(self, project, database, lines):sql_lines = []row_count = 1database_info = self.databases.get(database)conn = connect(host=database_info.get("ip"),port=3306,user=database_info.get("username"),password=database_info.get("password"),database=database_info.get("database"),charset='utf8mb4')for index, line in enumerate(lines):if line.startswith("--"):continuecurrent_sql = line.replace("\n", "")execute_info = self.execute_sql_and_get_execute_time(conn, database, current_sql)tables = extract_query_sql_table_names(current_sql)real_rows = ""for table in tables:total_rows = count_rows(conn, table)real_rows += f"{table}:{total_rows}行 "sql_line = {"row_count": row_count,"sql_description": "","sql": current_sql,"expect_rows": ",".join(tables),"real_rows": real_rows,"execute_time": execute_info["execute_time"],"execute_rows": execute_info["execute_rows"],"index_has_work": execute_info["index_has_work"],"project": project,"project": project,"database": database}sql_lines.append(sql_line)row_count += 1conn.close()return sql_linesdef execute_sql_and_get_execute_time(self, conn, database, sql):print(f"==================> {database}库正在执行SQL: {sql}")# 记录开始时间try:cs = conn.cursor()  # 获取光标start_time = time.time()cs.execute(sql)rows = cs.fetchall()# 记录结束时间end_time = time.time()# 计算执行时间execution_time = end_time - start_timeconn.commit()print(f"======>{database}库共花费{execution_time:.6f}秒执行完毕,{sql}")except Exception as e:print(e)return {"execute_rows": "", "execute_time": "", "index_has_work": ""}index_has_work = check_index_usage(conn, sql)return {"execute_rows": len(rows), "execute_time": f"{execution_time:.6f} 秒","index_has_work": "是" if index_has_work else "否"}def handle_log_file(self, filename):with open(self.input_dir + "/" + filename, "r", encoding="utf-8") as file:lines = file.readlines()pre_filename = filename.split(".")[0]with open(self.output_dir + "/" + pre_filename + ".csv", "w", newline='', encoding='utf-8-sig') as f:writer = csv.writer(f,  quoting=csv.QUOTE_MINIMAL)csv_title = ["序号", "SQL功能描述", "SQL", "预估业务数据量", "实际测试数据量", "执行时间", "执行结果","索引是否生效", "所属项目", "所在库"]writer.writerow(csv_title)info = pre_filename.split("_in_")project_name = info[0]database_name = info[1].split("_")[0]sql_lines = self.handle_sql_log(project_name, database_name, lines)for sql_line in sql_lines:write_line = [sql_line["row_count"],sql_line["sql_description"],sql_line["sql"],sql_line["expect_rows"],sql_line["real_rows"],sql_line["execute_time"],sql_line["execute_rows"],sql_line["index_has_work"],sql_line["project"],sql_line["database"]]writer.writerow(write_line)def do_work(self):files = self.get_all_input_files()for file in files:self.handle_log_file(file)if __name__ == '__main__':sql_speed_test = SqlSpeedTest()sql_speed_test.do_work()

写在最后

编程精选网(www.codehuber.com),程序员的终身学习网站已上线!

如果这篇【文章】有帮助到你,希望可以给【JavaGPT】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【JavaGPT】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!

相关文章:

Python实现Java mybatis-plus 产生的SQL自动化测试SQL速度和判断SQL是否走索引

Python实现Java mybatis-plus 产生的SQL自动化测试SQL速度和判断SQL是否走索引 文件目录如下 │ sql_speed_test.py │ ├─input │ data-report_in_visit_20240704.log │ resource_in_sso_20240704.log │ └─outputdata-report_in_visit_20240704.cs…...

UDP的报文结构及其注意事项

1. 概述 UDP(User Datagram Protocol)是一种无连接的传输层协议,它提供了一种简单的数据传输服务,不保证数据的可靠传输。在网络通信中,UDP通常用于一些对实时性要求较高、数据量较小、传输延迟较低的应用&#xff0c…...

MySQL深度分页问题深度解析与解决方案

文章目录 引言深度分页问题的原因解决方案方案一:使用主键索引优化方案二:使用子查询优化方案三:使用INNER JOIN优化方案四:使用搜索引擎 最佳实践结论 引言 在处理包含数百万条记录的大型数据表时,使用MySQL的LIMIT进…...

C#类型基础Part1-值类型与引用类型

C#类型基础Part1-值类型与引用类型 参考资料前言值类型引用类型装箱和拆箱 参考资料 《.NET之美–.NET关键技术深入与解析》 前言 C#中的类型一共分为两类,一类是值类型(Value Type),一类是引用类型(Reference Type&#xff09…...

被上市公司预判的EPS增速分析

EPS增速对二级市场投资和估值有着很显著的影响,上市公司显然也知道这一点。对于想要做市值管理的上市公司来说,调节EPS增速比调节EPS更加有效。因此《穿透财报:读懂财报中的逻辑与陷阱》中的作者在第四章正式提出了二级市场财务分析中的额动态…...

快速入门了解Ajax

博客主页:音符犹如代码系列专栏:JavaWeb关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Ajax的初识 意义:AJAX(Asynchronous JavaScript and…...

FPGA开发——呼吸灯的设计

一、原理 呼吸灯的原理主要基于‌PWM(脉冲宽度调制)技术,通过控制LED灯的占空比来实现亮度的逐渐变化。这种技术通过调整PWM信号的占空比,即高电平在一个周期内所占的比例,来控制LED灯的亮度。当占空比从0%逐渐变化到1…...

【数据结构】二叉树链式结构——感受递归的暴力美学

前言: 在上篇文章【数据结构】二叉树——顺序结构——堆及其实现中,实现了二叉树的顺序结构,使用堆来实现了二叉树这样一个数据结构;现在就来实现而二叉树的链式结构。 一、链式结构 链式结构,使用链表来表示一颗二叉树…...

开始尝试从0写一个项目--后端(三)

器材管理 和员工管理基本一致,就不赘述,展示代码为主 新增器材 表设计: 字段名 数据类型 说明 备注 id bigint 主键 自增 name varchar(32) 器材名字 img varchar(255) 图片 number BIGINT 器材数量 comment VARC…...

2024年7月解决Docker拉取镜像失败的实用方案,亲测有效

在Ubuntu 16.04、Debian 8、CentOS 7系统中,若遇到Docker拉取镜像失败的问题,以下是一些亲测有效的解决方案: 配置加速地址 首先,创建Docker配置目录:sudo mkdir -p /etc/docker然后,编辑daemon.json文件…...

基于内容的音乐推荐网站/基于ssm的音乐推荐系统/基于协同过滤推荐的音乐网站/基于vue的音乐平台

获取源码联系方式请查看文末🍅 摘 要 随着信息化时代的到来,系统管理都趋向于智能化、系统化,音乐推荐网站也不例外,但目前国内的有些公司仍然都使用人工管理,公司规模越来越大,同时信息量也越来越庞大&…...

STM32智能工业监控系统教程

目录 引言环境准备智能工业监控系统基础代码实现:实现智能工业监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:工业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能工业监控系统通…...

WEB渗透Web突破篇-SQL注入(MYSQL)

注释符 # -- 注意这里有个空格 /* hello */ /*! hello */ /*!32302 10*/ MYSQL version 3.23.02联合查询 得到列数 order by或group by 不断增加数字,直到得到报错响应 1 ORDER BY 1-- #True 1 ORDER BY 2-- #True 1 ORDER BY 3-- #True 1 ORDER BY 4-- #Fal…...

PDF解锁网站

https://smallpdf.com/cn/unlock-pdfhttps://smallpdf.com/cn/unlock-pdfhttps://www.freemypdf.comhttps://www.freemypdf.com...

【Redis】主从复制分析-基础

1 主从节点运行数据的存储 在主从复制中, 对于主节点, 从节点就是自身的一个客户端, 所以和普通的客户端一样, 会被组织为一个 client 的结构体。 typedef struct client {// 省略 } client;同时无论是从节点, 还是主节点, 在运行中的数据都存放在一个 redisServer 的结构体中…...

Transformer自然语言处理实战pdf阅读

一.第一章 欢迎来到transformer的世界 1.解码器-编码器框架 在Transformer出现之前,NLP的最新技术是LSTM等循环架构。这些架 构通过在神经网络连接使用反馈循环,允许信息从一步传播到另一 步,使其成为对文本等序列数据进行建模的理想选择。如…...

Python 高阶语法

前言: 我们通过上篇文章学习了Python的基础语法,接下来我们来学习Python的高阶语法 1.初识对象 在Python中我们可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的 面向对象包含 3 大主要特性:  封装  继承 …...

开始尝试从0写一个项目--前端(三)

器材管理板块 添加器材管理导航 src\views\home\Home.vue src\router\index.js src\views\equipment\Equipment.vue <template><div>hello!</div></template> 测试 搜索导航分页查询 src\views\equipment\Equipment.vue <template><div&…...

Visual stdio code 运行C项目环境搭建

参考 [1]VS Code 配置 C/C 编程运行环境&#xff08;保姆级教程&#xff09;_visual studio code c配置-CSDN博客 [2]最新VS code配置C/C环境(tasks.json, launch.json,c_cpp_properties.json)及运行多个文件、配置Cmake_vscode launch.json如何配置-CSDN博客 先装visual stdi…...

免杀笔记 -->API的整理Shellcode加密(过DeFender)

最近更新频率明显下降我懒&#xff0c;那么今天就来记录一下我们的一些常用的API的整理以及ShellCode的加密。 1.WinAPI整理 问我为什么要整理&#xff1f; 就是用起来的时候要左翻右翻 &#xff1a;&#xff1a; 烦死了 1.VirtualAlloc VirtualAlloc(NULL,sizeof(buf),MEM_…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...