百万级Excel导入数据库慢到崩溃?这5个优化技巧让你10分钟搞定!
百万级Excel导入数据库慢到崩溃?这5个优化技巧让你10分钟搞定!
一、Excel导入慢?先搞清楚这3个核心问题
在开始优化之前,我们首先要明白为什么Excel导入会这么慢。一般来说,主要有以下几个原因:
- 内存爆炸:传统方式会把整个Excel文件加载到内存,百万级数据很容易导致OOM
- 数据库瓶颈:单条插入数据,没有利用数据库的批量处理能力
- 校验开销:每条数据都进行复杂的业务校验,严重拖慢速度
之前在某电商公司做数据迁移时,就遇到过一个Excel导入的坑。当时用Apache POI直接读取一个50万行的Excel,结果程序运行5分钟后就抛出了OutOfMemoryError。后来才知道,原来POI的XSSFWorkbook会把整个文档树加载到内存中,对于大文件来说简直是灾难。
二、5个核心优化技巧,让导入速度提升10倍
1. 流式读取:告别内存溢出的噩梦
原理:不一次性加载整个Excel文件,而是像水流一样逐行读取数据。
实现方案:
- Apache POI的SXSSFWorkbook:适合处理大数据量的Excel
- Alibaba的EasyExcel:封装了POI,API更友好,性能更好
实战效果:之前处理50万行Excel需要2GB内存,用流式读取后只需要200MB内存,而且不会OOM。
之前做的一个电商商品数据导入项目,用EasyExcel的流式读取功能,成功处理了100万行的Excel文件,内存占用始终稳定在300MB以内。
2. 批量写入:让数据库飞起来
原理:数据库单条插入和批量插入的性能差异巨大,批量插入可以显著减少网络IO和事务开销。
实现方案:
- JDBC的addBatch和executeBatch方法
- MyBatis的批量插入功能
- 设置合理的批次大小(一般1000-5000条/批)
实战效果:某金融系统导入100万条交易记录,单条插入需要3小时,批量插入(每批2000条)只需要40分钟。
记得有一次,我们的财务系统需要导入大量的报销数据。一开始用单条插入,10万条数据用了1个多小时。后来改成每批2000条的批量插入,同样的数据只需要15分钟,效率提升了4倍多。
3. 并行处理:多线程分片加速
原理:把Excel数据分成多个分片,用多线程并行处理,可以充分利用CPU资源。
实现方案:
- 先获取Excel的总行数
- 根据线程数平均分配每线程处理的行数
- 每个线程独立读取和处理自己的分片
- 使用CountDownLatch或CompletableFuture等待所有线程完成
实战效果:某政府部门的人口数据导入,单线程处理需要2小时,用8线程并行处理后只需要30分钟。
不过这里要注意,线程数不是越多越好,要根据服务器的CPU核心数来合理设置。一般来说,线程数等于CPU核心数的2倍左右是比较合理的。
4. 校验优化:让校验不再成为瓶颈
原理:复杂的校验逻辑会严重拖慢导入速度,需要优化校验方式。
实现方案:
- 前置校验:在导入前对Excel格式进行校验
- 批量校验:对一批数据进行批量校验,而不是逐条校验
- 异步校验:将校验逻辑异步化,不阻塞主线程
- 索引优化:对校验中频繁查询的字段建立索引
实战效果:某电商平台的商品导入,优化前每条数据需要50ms校验时间,优化后批量校验每条约5ms,整体速度提升了10倍。
我之前遇到过一个项目,导入数据时需要校验商品分类是否存在,一开始是逐条查询数据库,导致校验时间比导入时间还长。后来改成先查询所有分类到内存中,再进行内存校验,校验时间直接从总耗时的80%降到了10%。
5. 临时表策略:化整为零的智慧
原理:先将数据导入临时表,再通过SQL语句进行数据清洗和转换,最后插入目标表。
实现方案:
- 创建与目标表结构相似的临时表
- 快速将数据导入临时表(可以关闭索引和约束)
- 通过SQL语句进行数据清洗、去重、转换
- 将清洗后的数据插入目标表
- 删除临时表
实战效果:某医疗系统导入患者数据,直接导入目标表需要2小时,使用临时表策略后只需要45分钟。
三、实战案例:从3小时到10分钟的蜕变
案例1:电商平台100万商品数据导入
背景:某电商平台需要将100万商品数据从Excel导入到MySQL数据库,原方案耗时3小时以上,经常出现OOM。
优化过程:
- 使用EasyExcel流式读取Excel,避免内存溢出
- 采用每批2000条的批量插入
- 开启4线程并行处理
- 将商品分类校验改为内存校验
优化结果:导入时间从3小时缩短到10分钟,内存占用稳定在500MB以内,没有出现OOM。
案例2:金融系统500万交易记录导入
背景:某金融系统需要导入500万条历史交易记录,原方案使用单线程+单条插入,耗时8小时以上。
优化过程:
- 使用临时表策略,先快速导入临时表
- 关闭临时表的索引和约束
- 使用LOAD DATA INFILE命令批量导入
- 在临时表中完成数据清洗后插入目标表
优化结果:导入时间从8小时缩短到1小时,效率提升了8倍。
案例3:政府部门人口数据迁移
背景:某政府部门需要迁移1000万条人口数据,原方案使用传统POI读取,经常内存溢出,导入失败。
优化过程:
- 使用POI的SXSSFWorkbook流式读取
- 分10个线程并行处理
- 使用JDBC的批量插入功能
- 优化数据库连接池配置
优化结果:成功导入1000万条数据,耗时2小时,没有出现内存溢出问题。
四、老码农的6点经验总结
- 避免一次性加载:永远不要试图把整个Excel文件加载到内存中
- 批量操作是王道:充分利用数据库的批量插入功能
- 并行处理要合理:根据CPU核心数设置适当的线程数
- 校验逻辑要优化:能批量校验就不要逐条校验,能内存校验就不要数据库校验
- 临时表很有用:对于复杂数据转换,临时表策略往往能事半功倍
- 监控和日志很重要:记录导入过程中的关键指标,便于后续优化
写在最后,处理百万级Excel导入,关键是要解决内存溢出和性能瓶颈问题。希望今天分享的这些技巧和案例,能帮助大家在遇到类似需求时少走弯路。如果觉得有用,欢迎点赞、转发,也欢迎在评论区分享你的Excel导入经验。
公众号:服务端技术精选
声明:本文原创,转载请注明出处。
标题:百万级Excel导入数据库慢到崩溃?这5个优化技巧让你10分钟搞定!
作者:jiangyi
地址:http://www.jiangyi.space/articles/2025/12/21/1766304293730.html