导出任务耗时如何优化

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 大量数据的导入导出时,请求一定非常耗时,页面一定会不停转圈圈,不可能让用户一直停留在这个页面转圈圈,这样并不友好。比较好的方式就事通过异步的方式,先提交任务,然后通过线程的处理数据。一次性如果导出大量数据时,需要批量查询结果到处。

大量数据的导入导出时,请求一定非常耗时,页面一定会不停转圈圈,不可能让用户一直停留在这个页面转圈圈,这样并不友好。

比较好的方式就事通过异步的方式,先提交任务,然后通过线程的处理数据。一次性如果导出大量数据时,需要批量查询结果到处。

导出功能设计:

前端页面设计如下: 新增 导出按钮 和导出记录按钮 导出记录页面字段如下: 批次号  时间  导出URL  操作(导出) 后端表结构

sql

代码解读

复制代码

create table export_record(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
 `batch_no` varchar(32)  DEFAULT NULL COMMENT '导入批次号',
 `export_type` varchar(3) DEFAULT NULL COMMENT '类型(1:订单导出)',
  `export_url` varchar(300) DEFAULT NULL COMMENT 'url',
 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  `create_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人代码',
  `create_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人名称',
  `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
  `last_update_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
  `last_update_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
   PRIMARY KEY (`id`),
   KEY `index_import_record` (`batch_no`) USING BTREE
)ENGINE=InnoDB  COMMENT='导出记录';

后端功能逻辑: 将导出的数据生成excel文件,并上传到服务器中,上传的文件生产的url保存记录,供前端页面下载excel文件

导入功能设计

前端页面设计如下:导入记录页面字段如下: 批次号  时间  总条数 成功条数 操作

sql

代码解读

复制代码

create table import_record (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
 `batch_no` varchar(32)  DEFAULT NULL COMMENT '导入批次号',
 `export_type` varchar(3) DEFAULT NULL COMMENT '类型(1:订单导出)',
  `total_num` int DEFAULT 0 COMMENT '总数量',
  `success_num` int DEFAULT 0 COMMENT '成功数量',
 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  `create_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人代码',
  `create_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人名称',
  `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
  `last_update_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
  `last_update_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
   PRIMARY KEY (`id`),
   KEY `index_import_record` (`batch_no`) USING BTREE
)ENGINE=InnoDB  COMMENT='导入记录';


create table import_record (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
 `batch_no` varchar(32)  DEFAULT NULL COMMENT '导入批次号',
 `export_type` varchar(3) DEFAULT NULL COMMENT '类型(1:订单导出)',
  `total_num` int DEFAULT 0 COMMENT '总数量',
  `success_num` int DEFAULT 0 COMMENT '成功数量',
 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  `create_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人代码',
  `create_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人名称',
  `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
  `last_update_code` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
  `last_update_name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后更新人',
   PRIMARY KEY (`id`),
   KEY `index_import_record` (`batch_no`) USING BTREE
)ENGINE=InnoDB  COMMENT='导入记录';

导入逻辑: 对导入的excel文件进行解析,并保存解析出来的数据。

大量数据查询拆分成批量任务查询

导出数据可能会导出大量数据,通常情况下,一次性查询大量数据导致负载压力的原因是在一次查询中同时检索了太多数据,并在内存中进行处理,这会占用大量系统资源,造成系统响应变慢和崩溃等问题。

mysql会将检索出来的数据都缓存到内存,一次性返回到服务端,这样会占用大量的内存资源,导致内存不足,从而影响系统运行稳定性。

解决的方式是批次处理,如分页查询数据,从而减少mysql查询占用的内存。

分页查询工具如下:

java

代码解读

复制代码

@CustomLog
public class PageBigDataUtil {

    /**
     * @param queryParam 查询条件
     * @param function 分页查询
     * @return
     */
    public static <T> List<T> pageBigData(T queryParam, Function<PageQueryBean<T>, PageQueryBean<T>> function) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> results = new ArrayList<>();
        int size = 500;
        int current = 1;
        for (; ; ) {
            PageQueryBean<T> pageParam = new PageQueryBean<>();
            SimplePage<T> simplePage = new SimplePage<>();
            simplePage.setPageSize(size);
            simplePage.setPageNum(current);
            pageParam.setPage(simplePage);
            pageParam.setParameter(queryParam);
            PageQueryBean<T> result = function.apply(pageParam);
            logger.keyword("分页批次任务").info("--------导入开始,本批次共:{} 轮,当前第{}轮", result.getPage().getPages(), current);
            if (DataUtil.isEmpty(result)) {
                break;
            }
            results.addAll(result.getPage().getList());
            if ((long) size * current >= result.getPage().getTotal()) {
                break;
            }
            current++;
        }
        stopWatch.stop();
        logger.info("批次任务已结束,分页批次任务:{},获取总记录数:{},总耗时:{}秒", current, results.size(), stopWatch.getTotalTimeSeconds());
        return results;
    }

    /**
     *
     * @param queryParam 查询条件
     * @param function 分页查询
     * @param consumer 批次消费
     * @param <T>
     */
    public static <T> void handleBigData(T queryParam, Function<PageQueryBean<T>, PageQueryBean<T>> function, Consumer<List<T>> consumer) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        int size = 500;
        int current = 1;
        for (; ; ) {
            PageQueryBean<T> pageParam = new PageQueryBean<>();
            SimplePage<T> simplePage = new SimplePage<>();
            simplePage.setPageSize(size);
            simplePage.setPageNum(current);
            pageParam.setPage(simplePage);
            pageParam.setParameter(queryParam);
            PageQueryBean<T> result = function.apply(pageParam);
            if (DataUtil.isEmpty(result)) {
                break;
            }
            // 业务处理
            consumer.accept(result.getPage().getList());
            logger.keyword("分页批次任务").info("--------导入开始,本批次共:{} 轮,当前第{}轮", result.getPage().getPages(), current);
            if ((long) size * current >= result.getPage().getTotal()) {
                break;
            }
            current++;
        }
        stopWatch.stop();
        logger.info("批次任务已结束,总耗时:{}秒", stopWatch.getTotalTimeSeconds());
    }
}



相关文章
|
域名解析 应用服务中间件 网络安全
自己的ip地址被别人的域名解析到?已解决
自己的ip地址被别人的域名解析到?已解决
859 0
|
编解码 NoSQL Java
使用Spring Boot + Redis 队列实现视频文件上传及FFmpeg转码的技术分享
【8月更文挑战第30天】在当前的互联网应用中,视频内容的处理与分发已成为不可或缺的一部分。对于视频平台而言,高效、稳定地处理用户上传的视频文件,并对其进行转码以适应不同设备的播放需求,是提升用户体验的关键。本文将围绕使用Spring Boot结合Redis队列技术来实现视频文件上传及FFmpeg转码的过程,分享一系列技术干货。
1121 4
|
机器学习/深度学习 数据采集 人工智能
文档智能和检索增强生成(RAG)——构建LLM知识库
本次体验活动聚焦于文档智能与检索增强生成(RAG)结合构建的LLM知识库,重点测试了文档内容清洗、向量化、问答召回及Prompt提供上下文信息的能力。结果显示,系统在自动化处理、处理效率和准确性方面表现出色,但在特定行业术语识别、自定义向量化选项、复杂问题处理和Prompt模板丰富度等方面仍有提升空间。
704 0
|
机器学习/深度学习 编解码 算法
《多模态数据信息提取解决方案的体验与部署》
《多模态数据信息提取》解决方案提供了一站式的文本、图像和音频数据处理平台,通过先进算法实现关键信息的高效提取。函数应用模板简化了部署流程,标准化接口和自动化配置降低了技术门槛。然而,参数设置、错误处理和文档说明等方面存在细节问题,需进一步优化以提高用户体验和部署效率。改进措施包括加强参数说明、完善错误处理机制及优化文档,推动多模态数据处理技术的发展。
365 23
|
XML Java 测试技术
testNG框架从入门到精通
testNG框架从入门到精通
testNG框架从入门到精通
|
Java 程序员 容器
十分钟搞懂依赖注入
依赖注入(DI)是软件开发中的关键技术,它将类的依赖关系转移至外部管理,提升了代码的模块化和可测试性。如同炒菜时调料不由厨师直接添加,而是由调料师准备并递送,程序员只需声明所需依赖,外部机制如DI容器会负责实例化并注入这些依赖。这样,类变得更灵活且易于测试,同时也促进了代码的模块化。例如,在Java中,可以通过构造函数注入Logger接口的不同实现(如ConsoleLogger和FileLogger),使Application类与其具体实现解耦。
641 1
|
Linux Windows
端口占用的解决方法
本文介绍了在Windows和Linux系统中解决端口占用问题的方法,包括使用`netstat`命令查看端口占用情况、`tasklist`命令查找对应进程,以及使用`taskkill`命令终止进程,在Linux系统中则使用`netstat`或`lsof`命令查找占用端口的进程,并用`kill`命令结束进程。
Uni-App - 用户没有登录自动跳转登录页面方案
Uni-App - 用户没有登录自动跳转登录页面方案
1670 0
Uni-App - 用户没有登录自动跳转登录页面方案
|
小程序 JavaScript 开发工具
微信小程序开发工具的使用,各个配置文件详解,小程序开发快速入门(一)
微信小程序开发工具的使用,各个配置文件详解,小程序开发快速入门(一)
1137 1
|
Linux
如何在Linux中删除目录的所有文件?
如何在Linux中删除目录的所有文件?
1786 1
如何在Linux中删除目录的所有文件?