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.log和resource_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 | 预估业务数据量 | 实际测试数据量 | 执行时间 | 执行结果 | 索引是否生效 | 所属项目 | 所在库 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 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 | t_bw_article_daily_statistic | t_bw_article_daily_statistic:5741行 | 0.419603 秒 | 462 | 是 | data-report | visit | |
| 2 | 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 | t_bw_article_daily_statistic_202406 | t_bw_article_daily_statistic_202406:296358行 | 0.291532 秒 | 2691 | 是 | data-report | visit |
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通常用于一些对实时性要求较高、数据量较小、传输延迟较低的应用,…...
MySQL深度分页问题深度解析与解决方案
文章目录 引言深度分页问题的原因解决方案方案一:使用主键索引优化方案二:使用子查询优化方案三:使用INNER JOIN优化方案四:使用搜索引擎 最佳实践结论 引言 在处理包含数百万条记录的大型数据表时,使用MySQL的LIMIT进…...
C#类型基础Part1-值类型与引用类型
C#类型基础Part1-值类型与引用类型 参考资料前言值类型引用类型装箱和拆箱 参考资料 《.NET之美–.NET关键技术深入与解析》 前言 C#中的类型一共分为两类,一类是值类型(Value Type),一类是引用类型(Reference Type)…...
被上市公司预判的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 编程运行环境(保姆级教程)_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)
最近更新频率明显下降我懒,那么今天就来记录一下我们的一些常用的API的整理以及ShellCode的加密。 1.WinAPI整理 问我为什么要整理? 就是用起来的时候要左翻右翻 :: 烦死了 1.VirtualAlloc VirtualAlloc(NULL,sizeof(buf),MEM_…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
用 FFmpeg 实现 RTMP 推流直播
RTMP(Real-Time Messaging Protocol) 是直播行业中常用的传输协议。 一般来说,直播服务商会给你: ✅ 一个 RTMP 推流地址(你推视频上去) ✅ 一个 HLS 或 FLV 拉流地址(观众观看用)…...
