深度翻页导出导致慢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编码进行坐标系转换&…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...