深度翻页导出导致慢SQL,mysqlCPU飙升优化方案
慢SQL原因分析:
1.深度翻页
2.多表JOIN
3. 大IN
4. id倒排序
本文针对深度翻页的优化进行探讨
方案1:
将limit offset, pageSize的方式改成 id > xx limit pageSize.
这样能走Id索引,提高速度。
缺点:不能使用多线程,入参ID从上页结果。
方案2:
基于 方案1再优化, 将limit offset, pageSize 的方式改成 id > startId and id< endId .
一次性查出符合条件的ID范围,然后切分ID范围进行查询。(可分实际ID划分,或逻辑范围划分)
优点: 能用多线程并发查询。
缺点:逻辑范围划分有的id范围可能无数据,进行无效查询。
方案3:
终极方案:设置fetchSize,思想是 一次查询在Mysql侧缓冲全量数据,程序侧通过游标cursor批量读取数据,通过回调函数resulthandler处理数据。
优点: 不用多次和Mysql查询,一次查询多次读取数据。回调里可以使用多线程操作数据。
缺点: Mysql要缓冲全量数据,内存飙升

方案二步骤:
(1) 查询 对应表的ID范围,COUNT条数
(2) 根据count条数,和每页数量,计算页数,根据页数 和 ID范围进行ID范围切分。
(3)根据ID范围,发起多线程并发查询。
其中具体核心逻辑代码:
ID范围查询
<!-- 统计分页查询总条数 --><select id="findIdRange" resultType="com.xyy.ms.export.core.erpreport.dto.ExportIdRangeDTO">selectmin(b.id) as minId, max(b.id) as maxId, count(1) as countfrom storage_batchnum b<include refid="batchNumExportWhere"></include></select>
ID切分逻辑:
package com.xyy.ms.export.core.erpreport.dto;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;/*** @author stivenjin* @version 1.0* @description 说明: 取表中最小和最大ID, 用ID翻页查询,避免深度翻页(批号库存翻页导出)* 翻页优化步骤:* 1:根据ID范围,进行切分组* 2:用每组 的边界值进行id范围翻页查询。* @date 2023/9/1 18:10*/
@Getter
@Setter
@ToString
@AllArgsConstructor
public class ExportIdRangeDTO implements Serializable {/*** 最小ID*/private int minId = 0;/*** 最大ID*/private int maxId = 0;/*** 总条数*/private long count = 0;public boolean isValid() {return minId > 0 && maxId > 0;}/*** 按页数分隔ID范围* @param pageCount* @return*/public List<ExportIdRangeDTO> splitByPageCount(int pageCount) {List<ExportIdRangeDTO> splitList = new ArrayList<ExportIdRangeDTO>();int startId = minId;int endId = maxId;int pageSize = (int)Math.ceil((Double.valueOf(maxId) - Double.valueOf(minId)) / pageCount);System.out.println("pageSize:" + pageSize + ",pageCount:" + pageCount);int tmp = endId;for(int i = 1 ;i<=pageCount;i++){if(startId <= tmp){if(startId + pageSize <= tmp){endId = startId + pageSize ;}else{endId = tmp;}}else{break;}//System.out.println("循环调用:" + startId + " : " + endId);splitList.add(new ExportIdRangeDTO(startId, endId, 0));if(endId <= tmp){startId = endId +1;}}return splitList;}public static void main(String[] args) {ExportIdRangeDTO dto = new ExportIdRangeDTO(100,823540, 0);dto.splitByPageCount(10);System.out.println("切分一片原始:" + dto.getMinId() + " : " + dto.getMaxId());}
}
<if test="minId != null and maxId != null">and b.id >= #{minId} and b.id <= #{maxId}
</if>
按ID范围切分后,可用多线程并发查询导出
taskExecutor.submit
// 增加顺序按起点ID导出模式,避免深度翻页慢SQL(之前是多线程并发深度翻页查MYSQL,mysql cpu飙升)if (batchNumExportUseId) {ExportIdRangeDTO idRangeRes = exportStorageBatchNumApi.findIdRange(params);logger.info(" taskId [{}] 开始-异步顺序导出,idRange={}",taskId, JSON.toJSONString(idRangeRes));if (idRangeRes != null && idRangeRes.isValid()) {paramsObject.put("pageSize", StorageWebConstant.PURCHASE_CALL_PAGESIZE);int pageCnt = (int)(idRangeRes.getCount()/StorageWebConstant.PURCHASE_CALL_PAGESIZE);pageCnt = pageCnt + (idRangeRes.getCount()%StorageWebConstant.PURCHASE_CALL_PAGESIZE == 0 ? 0:1);List<ExportIdRangeDTO> idRangeList = idRangeRes.splitByPageCount(pageCnt);AtomicInteger pageNum = new AtomicInteger(0);for (ExportIdRangeDTO idRange : idRangeList) {int pn = pageNum.incrementAndGet();Map<String, Object> exportParamMap = new HashMap<>();exportParamMap.putAll(paramsObject);exportParamMap.put("pageNum", pn);exportParamMap.put("minId", idRange.getMinId());exportParamMap.put("maxId", idRange.getMaxId());logger.info("## taskId [" + taskId + "]开始导出,第 " + pn + " 页 {}-{}", idRange.getMaxId(), idRange.getMaxId());exportMap.putIfAbsent(pn, taskExecutor.submit(() -> storageReportService.listStorageBatchNumReportView(exportParamMap)));}for (int i = 1; i <= pageNum.get(); i++) {List<StorageReportViewVo> list = exportMap.get(i).get().getList();ExportExcelUtil.insertDataToExcel(work, colName, list, line, true);line = line + list.size();}}}
相关文章:
深度翻页导出导致慢SQL,mysqlCPU飙升优化方案
慢SQL原因分析: 1.深度翻页 2.多表JOIN 3. 大IN 4. id倒排序 本文针对深度翻页的优化进行探讨 方案1: 将limit offset, pageSize的方式改成 id > xx limit pageSize. 这样能走Id索引,提高速度。 缺点:不能使用多线程…...
小谈设计模式(1)—总序
小谈设计模式(1)—总序 开始操作设计模式总论设计模式是什么组成要素模式名称问题描述解决方案效果描述 设计模式有什么作用提供可重用的解决方案提高代码的可读性和可维护性促进代码的可扩展性提高代码的灵活性和可重用性促进团队合作和沟通作用总结 为…...
【c++】stringstream基础:实现数据类型转换和字符串分割
传统实现整型转换为字符串需要使用itoa或者sprintf,对于itoa和atoi的使用可以看文章: atoi和itoa极简无废话概述 但是用这两个函数进行转换时,所需要的空间事先不确定,所以可能造成程序崩溃,今天介绍的stringstream可…...
Java基础学习笔记-5
前言 Java编程语言是一门广泛应用于软件开发领域的高级编程语言。它的强大特性和跨平台性使其成为许多开发者的首选语言。本文将介绍一些Java编程的关键概念,包括函数重载、可变参数、值传递、递归等,这些概念是Java编程的基础,对于理解和掌…...
合同交付类项目如何高效管理?
美国项目管理协会(PMI)保罗格蕾斯曾说:“当今社会,一切都是项目,一切也将成为项目。”在“万事皆项目”的背景下,企业在运营过程中会产生大量的项目型业务活动,例如:举办市场活动、产品研发、进行企业内训、采购招标、工程建设等等。那么按照…...
两性养生网站源码 生活类减肥网站源码 健康网模板源码 支持QQ登录和百度主动推送
本套模板非常适合生活类,两性类,减肥类等等类型的网站,这类型网站比较好做流量,因为客户群体众多, 可以自行改内容为其他类型网站模板总体非常简洁漂亮,配色合理,视觉舒服,并且配合…...
CentOS7安装Jenkins(更改默认运行的端口号8080->16060)
第一步: 端口号为默认8080 的安装是:Jenkins安装配置 第二步:将默认运行端口8080—>16060 首先修改配置文件 修改配置文件:vi /etc/sysconfig/jenkins修改内容:# 服务监听端口JENKINS_PORT"16060"然后…...
Java开发之Mysql【面试篇 完结版】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、知识体系二、Mysql-优化1. 优化-如何定位慢查询① 问题引入② 解决方案③ 问题总结④ 实战面试 2. 优化-sql执行很慢,如何解决① 问题引入② 解…...
【实战】十二、自动化测试 —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十九)
文章目录 一、项目起航:项目初始化与配置二、React 与 Hook 应用:实现项目列表三、TS 应用:JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...
【人月神话】重新探索人月神话:软件工程的现实与挑战
人月神话是一篇由美国软件工程师弗雷德里克布鲁克斯所写的软件工程经典之作,最早发表于1975年。这篇文章的全名是《人月神话:软件工程的神话与现实》(The Mythical Man-Month: Essays on Software Engineering),它涵盖…...
电阻和电容
目录 1、常见的电阻器 2、电容 编辑 1、常见的电阻器 对于电阻需要了解三个参数(查询电阻的数据手册): 1、封装:就是电阻的尺寸或者大小,看焊在你的pcb板上是否合适。 2、标称:电阻的电阻大小、精度、…...
01-Java-日志框架
1 日志技术概述 1.1 什么是日志技术 日志技术是一种记录和存储应用程序运行时信息的技术。它可以捕获应用程序的状态、事件、错误和警告等信息,并将其保存到日志文件或其他存储介质中。日志技术可以帮助开发人员和运维团队了解应用程序的运行情况,进…...
【js】map、filter、reduce、fill(待补充...)
const arr [{ id: 1, flag: true },{ id: 2, flag: true },{ id: 3, flag: false },{ id: 4, flag: true }, ]map:返回的是对每个元素进行操作后的结果数组,这个数组的长度和原数组相同 const result arr.map((item: any) > {return item.flag fa…...
【JPC出版】第二届能源与电力系统国际学术会议 (ICEEPS 2023)
第二届能源与电力系统国际学术会议 (ICEEPS 2023) 2023 2nd International Conference on Energy and Electrical Power Systems 第二届能源与电力系统国际学术会议 (ICEEPS 2023)将于2023年10月27日至29日在中国厦门举行。ICEEPS 将汇集能源科学、电气工程和电力系统领域的…...
51单片机的简易篮球计分器倒计时仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
51单片机的简易篮球计分器倒计时仿真设计( proteus仿真程序原理图报告讲解视频) 1.主要功能:2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接 51单片机的简易篮球计分器倒计时仿真设计( proteus仿真程序原理图报告讲解视频…...
医院安全不良事件报告系统源码 PHP+ vue2+element+ laravel8+ mysql5.7+ vscode开发
不良事件上报系统通过 “事前的人员知识培训管理和制度落地促进”、“事中的事件上报和跟进处理”、 以及 “事后的原因分析和工作持续优化”,结合预存上百套已正在使用的模板,帮助医院从对护理事件、药品事件、医疗器械事件、医院感染事件、输血事件、意…...
Mybatis -- 读取 DATE 类型字段时可能遇到的问题(夏令时问题)
在使用 MYBATIS 读取数据库字段的时候,我们一般需要为查询字段指定数据类型。特别是当我们使用 mybatis generator 去生成对应的接口代码时,会自动按照数据库字段类型生成响应映射规则的代码。 如下,左侧是 date 类型生成的字段映射规则&…...
第10节-PhotoShop基础课程-选区工具
文章目录 前言1.矩形选区 shift 是正方形1.任意比例2.等比绘制 先点击再按shift3.中心绘制1.任意比例 先点击再按Alt2.等比绘制 先点击再按Alt Shift 4.移动选区 按住空格 2.椭圆选区1.椭圆选区2.正圆选区 shift键3.中心圆选区 Alt Shift 3.选取选项1. 选区1.建立选区2.加选 s…...
【C++】C++动态内存管理
🏳️🌈C/C内存分布 说明: 1.我们的代码并非放在代码段里的,而是以文件的形式存在磁盘上的。 代码经过编译链接形成的二进制指令,才是放进代码段里的。(即可执行代码) 2.“abcd”如果没有被c…...
Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角
场景 Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等): Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等)_jts-core_霸道流氓气质的博客-CSDN博客 JavaGeoTools实现WKT数据根据EPSG编码进行坐标系转换&…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
