excel导入导出百万级数据优化

背景

在我前年找实习的时候,遇到了面试官问我:mysql从excel导出百万级数据,该怎么做?我听到的第一反应是:我*,我哪去接触百万级的数据,你们导出的数据是什么?我还是一个才找实习工作的大学生啊。后来也有各种各样的八股文,介绍这种导入导出的优化,然而我拒绝囫囵吞枣式学习,背八股文的方式学习。shigen也在这里实测了,在此先感谢蜗牛,为我提供了高质量的代码参考和分析案例。

分析

百万级数据导出Excel

循环导出

新手和没做过这方面的程序员们别不好意思,我知道你们怎么想的。不就是查询数据写到excel里边吗,看我的。先一条条的读取数据放在一个list里边,然后用Apache的POI写入excel,完了提供下载就可以了。

好坏喔在这里不做评论哈,自己心里肯定过意不去的。百万数据,我得运行多久!

批量查询导出

这种想法的技术就知道sql这一部分可以优化了,我们分批查询分批写入,然后汇总成一个Excel文件,直接下载。shigen就写一点伪代码吧。

Execel  excel = new Excel();
for (int i=0;i< page;i++) {
  List<data> data = getFromDB(i, pagesize);
  excel.write(data);
}
excel.close();
线程池走起

知道循环了,知道了循环里的方法都是一样,参数不一样了。那我就获得了一个消息;我可以用线程池了。但是,我excel的最终写入完成是需要知道的,CompletableFuture这就派上了用场。只有全部的任务完成之后,才会刷新流,标志着excel的写入完成。在此,看看shigen的代码设计吧。

线程池异步导出

循环导出

为什么还要提到这个呢,在批量查询导出中不是不建议循环,然后读取写入数据吗?是的,shigen确实是这样讲的。但是,如果你有以下的两种情况,也许这种方式是你的首选,也是最优解。

  • 不会用异步任务,不会线程池
  • 导出的数据主键ID是连续的

第一种情况就不多说了,首选,也是人思考解决问题的本能。我只说第二种。涉及到了sql的优化了。

select * from user limit 10, 1000;
select * from user where id>=10 limit 1000;

两种sql,你猜猜哪种效率会更高呢?shigen直接揭晓答案,知道原因的也欢迎在评论区交流。第二种效率更高。

那我第二种方式写的代码是这样的。

循环分页导出

那这两种方式我测试了一下,执行的时间分别是:271ms 125ms。也明显的感觉到第二种代码更简单对吧。

百万级数据导入Excel

这个也依旧的麻烦,有人说不就是把之前的操作反过来的吗?是的,但是性能处理不好,要么花费很长的时间,要么直接OOM了。

以下是shigen的分析:

从excel导入100万数据到mysql

  • 首先是easyExcel分批读取Excel中的100w数据 EasyExcelGeneralDataListener按照sheet页一行行的数据读取
  • 其次就是往DB里插入,怎么去插入这20w条数据,批量插入 同样也不能使用Mybatis的批量插入,会读取数据到内存中,事务整体提交
  • 使用JDBC+事务的批量操作将数据插入到数据库(分批读取+JDBC分批插入+手动事务控制)

分析的过程就是这样,那怎么实现呢?展示一下shigen写的代码:

    @GetMapping("/importExcel")
    public void importExcel(@RequestParam("file") MultipartFile file) throws IOException {
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("file为空");
        }
        InputStream inputStream = file.getInputStream();
        // 记录开始读取Excel时间,也是导入程序开始时间
        long startReadTime = System.currentTimeMillis();
        log.info("------开始读取Excel的Sheet时间(包括导入数据过程):" + startReadTime + "ms------");
        // 读取所有Sheet的数据.每次读完一个Sheet就会调用这个方法
        EasyExcel.read(inputStream, new EasyExcelGeneralDataListener(userService)).doReadAll();
        long endReadTime = System.currentTimeMillis();
        log.info("------结束读取耗时" + (endReadTime - startReadTime) + "ms------");
    }

那么重点就在EasyExcelGeneralDataListener里边:关于它的使用可以参考博客使用easyexcel读excel(实现通用listener)。我直接上shigen的代码了。

EasyExcelGeneralDataListener的实现

总结

以上就是Excel导入导出百万级数据的优化思路了。可以作为案例参考和代码模板的使用,代码地址在这里。也欢迎大家的评论交流。觉得文章不错的话,记得点赞、在看、转发、关注哈

shigen一起,每天不一样!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/85160.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python实战【外星人入侵】游戏并改编为【梅西vsC罗】(球迷整活)——搭建环境、源码、读取最高分及生成可执行的.exe文件

文章目录 &#x1f3a5;前言&#x1f4bc;安装Pygame&#x1f50b;游戏的实现读写并存储【外星人入侵】游戏最高分游戏源码alien_invasion.pygame_functions.pyship.pyalien.pybullet.pybutton.pyscoreboard.pygame_stats.pysettings.py宇宙飞船和外星人的 .bmp类型文件 &#…

Go语言入门指南:基础语法和常用特性(下)

上一节&#xff0c;我们了解Go语言特性以及第一个Go语言程序——Hello World&#xff0c;这一节就让我们更深入的了解一下Go语言的**基础语法**吧&#xff01; 一、行分隔符 在 Go 程序中&#xff0c;一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ;…

解决IDEA tomcat控制台只有server日志

解决IDEA tomcat控制台只有server日志 确认tomcatxxx/conf/logging.properties文件是否存在&#xff0c;存在就会有。前提是在run configuration配置了打印多个日志

K8s+Docker+KubeSphere+DevOps笔记

K8sDockerKubeSphereDevOps 前言一、阿里云服务器开通二、docker基本概念1.一次构建、到处运行2、docker基础命令操作3、docker进阶操作1.部署redis中间件2.打包docker镜像 三、kubernetes 大规模容器编排系统1、基础概念&#xff1a;1、服务发现和负载均衡2、存储编排3、自动部…

概率论与数理统计:第七章:参数估计 第八章:假设检验

文章目录 Ch7. 参数估计7.1 点估计1.矩估计2.最大似然估计(1)离散型(2)连续型 7.2 评价估计量优良性的标准(1)无偏性 (无偏估计)(2)有效性(3)一致性 7.3 区间估计1.置信区间、置信度2.求μ的置信区间 Ch8. 假设检验1.拒绝域α、接受域1-α、H₀原假设、H₁备择假设2.双边检验、…

操作符详解(2)

9.条件操作符 由问号和冒号组成&#xff0c;有三个表达式&#xff0c;有三个操作符&#xff0c;所以条件操作符是唯一的一个三目操作符&#xff0c;exp1为真&#xff0c;exp2则计算&#xff0c;exp3不算&#xff0c;整个表达式的结果就是exp2的结果。exp1为假&#xff0c;exp2…

【M波段2D双树(希尔伯特)小波多分量图像去噪】基于定向M波段双树(希尔伯特)小波对多分量/彩色图像进行降噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

如何使用CSS实现一个瀑布流布局?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现瀑布流布局⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚…

qiiuzhiji4

本篇是从慧与离职后到2023年8月21日这段时间的经历 2023/7/31至2023/8/21 本篇初次写于2023年8月21日 从慧与离职后基本上就是在专心找工作了&#xff0c;但是有在这段时间找工作经历的人都明白&#xff0c;IT行业不复以往了。尤其是对于我这样的普通二本学历的人来说&#xff…

阿里云席明贤:明天的视频云2.0

编者按 本文是“解构多媒体新常态”系列文章的第二篇&#xff0c;LiveVideoStack对话了阿里云视频云负责人席明贤&#xff08;花名右贤&#xff09;。面对风云变幻的内外环境&#xff0c;阿里云在视频云赛道是坚定向前的&#xff0c;在与右贤的接触中&#xff0c;他给我留下非常…

ZLMediakit-method ANNOUNCE failed: 401 Unauthorized

使用ffmpeg推流&#xff1a; nohup ffmpeg -stream_loop -1 -re -i "/usr/local/mp4/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://10.55.134.12/live/test &[rootlocalhost ~]# ffmpeg -stream_loop -1 -re -i "/usr/local/mp…

SpringBoot+WebSocket搭建多人在线聊天环境

一、WebSocket是什么&#xff1f; WebSocket是在单个TCP连接上进行全双工通信的协议&#xff0c;可以在服务器和客户端之间建立双向通信通道。 WebSocket 首先与服务器建立常规 HTTP 连接&#xff0c;然后通过发送Upgrade标头将其升级为双向 WebSocket 连接。 WebSocket使得…

Vue2入门学习汇总

1.介绍及安装 1.1 介绍 Vue是一套构建用户界面的渐进式框架。Vue只关注视图层&#xff0c;采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 学习vue之前主要掌握的知识&#xff1a;HTML、CSS、JavaScript、TypeScript …

基于PyQt+mysql图书管理系统

1 需求分析 针对图书馆的图书管理系统数据库设计&#xff0c;分别对图书馆的读者、一般工作人员和部门负责人进行详细地分析&#xff0c;总结出如下的需求信息: &#xff08;1&#xff09;图书馆中的图书具有书号、书名、作者、馆藏册数、在馆册数、价格、出版社及摘要等必要信…

Java数据库连接池原理及spring boot使用数据库连接池(HikariCP、Druid)

和线程池类似&#xff0c;数据库连接池的作用是建立一些和数据库的连接供需要连接数据库的业务使用&#xff0c;避免了每次和数据库建立、销毁连接的性能消耗&#xff0c;通过设置连接池参数可以防止建立连接过多导致服务宕机等&#xff0c;以下介绍Java中主要使用的几种数据库…

关于数据中心存储智能运维的思考

随着互联网和大数据的快速发展&#xff0c;数据中心存储的重要性也日益凸显。在本文中&#xff0c;将深入探讨数据中心存储智能运维的历史变迁、当前的发展状态和未来的运维趋势。 数据中心存储运维的历史变迁可以分为以下几个阶段&#xff1a; 人工运维阶段 最初&#xff0c…

什么是PPS和TOD时序?授时防护设备是什么?

介绍 PPS和TOD PPS和TOD是两种用于精确时间同步的技术&#xff0c;它们在许多领域都有广泛的应用&#xff0c;总的来说&#xff0c;PPS和TOD被广泛应用于各种需要高度精确时间同步的领域&#xff0c;包括通信、测量、测试、系统集成和计算机网络等。 一、PPS PPS&#xff08…

EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问【无公网IP内网穿透】

憧憬blog主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是移动开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索iOS开发的无限可能&#xff01; &#x1f525;我们与您分享最新的技术洞察和实战经验&#xff0…

计算机视觉掩模区域与二值图像

掩模区域 在图像处理中&#xff0c;我们经常需要对图像中的某些特定区域进行操作&#xff0c;例如对某个区域进行滤波、变换、裁剪或者其他处理。为了实现这些操作&#xff0c;我们需要明确指定这些区域&#xff0c;这就是掩模区域的作用。 掩模区域通常由一个二值图像表示&…

【使用Node.js搭建自己的HTTP服务器】

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…