news 2026/2/8 22:31:01

批量导入 10 万条数据入库如何实现?—— 从“卡死”到“秒级完成”(Spring Boot + MySQL 实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
批量导入 10 万条数据入库如何实现?—— 从“卡死”到“秒级完成”(Spring Boot + MySQL 实战)

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)


一、真实痛点:为什么你导入 10 万条数据会卡死?

  • 循环 10 万次,每次INSERT INTO ...
  • 导致数据库连接超时、CPU 100%、内存溢出?
  • 导入花了 2 小时,老板急得跳脚?

🚨根本原因:你用了最原始的单条插入方式,而没用批量处理 + 事务优化 + 连接池调优

本文将手把手教你用Spring Boot + JDBC + MySQL实现10 万条数据 5 秒内入库,附完整代码、反例对比、性能压测!


二、反例警告:这些写法千万别用!

❌ 反例 1:循环单条插入(性能灾难!)

// 每次都开事务、建连接、网络往返 → 10 万次 = 灾难! for (User user : users) { jdbcTemplate.update("INSERT INTO users(name, email) VALUES (?, ?)", user.getName(), user.getEmail()); }

💥实测结果(10 万条)

  • 耗时:1200+ 秒(20 分钟)
  • 数据库 CPU:90%+
  • 网络 I/O:爆炸

❌ 反例 2:全量加载到内存(OOM 风险!)

// 一次性读 10 万条 Excel 到 List<User> → 内存直接爆! List<User> users = excelService.readAll("huge_file.xlsx"); userDao.batchInsert(users);

⚠️ 如果文件是 100 万行?服务器直接OutOfMemoryError


三、正确姿势:分页流式读取 + 批量插入 + 事务控制

✅ 核心思想:

  1. 分块读取:每次读 1000 行,避免 OOM;
  2. 批量插入:每 1000 条执行一次batchUpdate
  3. 手动事务:每批一个事务,失败可回滚,成功快提交;
  4. 关闭自动提交:减少事务开销。

四、手把手实战:Spring Boot 实现高效批量导入

第一步:配置 MySQL(关键!)

# application.yml spring: datasource: url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC &rewriteBatchedStatements=true # ←←← 开启批量重写(性能提升 10 倍!) &useServerPrepStmts=false # 批量插入时关闭服务端预编译 username: root password: 123456 hikari: data-source-properties: cachePrepStmts: true prepStmtCacheSize: 250 prepStmtCacheSqlLimit: 2048

🔑rewriteBatchedStatements=true是 MySQL 批量插入提速的关键!


第二步:DAO 层 —— 批量插入方法

@Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; // 每次插入一批(如 1000 条) public void batchInsert(List<User> users) { String sql = "INSERT INTO users(name, email, phone) VALUES (?, ?, ?)"; jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { User user = users.get(i); ps.setString(1, user.getName()); ps.setString(2, user.getEmail()); ps.setString(3, user.getPhone()); } @Override public int getBatchSize() { return users.size(); } }); } }

第三步:Service 层 —— 分块处理 + 事务控制

@Service @Slf4j public class DataImportService { @Autowired private UserDao userDao; // 每批处理 1000 条 private static final int BATCH_SIZE = 1000; @Transactional // ←←← 整个方法一个大事务(可选,见下文说明) public void importUsersFromExcel(String filePath) throws Exception { // 使用流式读取,避免内存溢出 try (InputStream is = new FileInputStream(filePath)) { ExcelReader reader = EasyExcel.read(is, User.class, new AnalysisEventListener<User>() { private List<User> batch = new ArrayList<>(); @Override public void invoke(User user, AnalysisContext context) { batch.add(user); // 达到批次大小,执行批量插入 if (batch.size() >= BATCH_SIZE) { userDao.batchInsert(batch); log.info("已导入 {} 条", context.readRowHolder().getRowIndex()); batch.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { // 处理最后一批不足 1000 的数据 if (!batch.isEmpty()) { userDao.batchInsert(batch); batch.clear(); } } }).build(); reader.readAll(); } } }

✅ 使用 EasyExcel 实现SAX 模式流式读取,100 万行也不怕 OOM!


五、事务策略选择:大事务 vs 小事务

策略优点缺点适用场景
整个导入一个事务@Transactional数据强一致,失败全回滚事务太大,可能超时、锁表数据量小(<1万),要求原子性
每批一个事务(手动控制)快速提交,失败只影响当前批部分成功部分失败推荐!10万+ 数据首选

✅ 推荐:每批一个事务(去掉@Transactional,改用手动)

// 在 Service 中注入 PlatformTransactionManager @Autowired private PlatformTransactionManager transactionManager; public void importUsersFromExcel(String filePath) throws Exception { // ... @Override public void invoke(User user, AnalysisContext context) { batch.add(user); if (batch.size() >= BATCH_SIZE) { // 手动开启事务 TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { userDao.batchInsert(batch); transactionManager.commit(status); // 提交 } catch (Exception e) { transactionManager.rollback(status); // 回滚当前批 log.error("批次导入失败,已回滚", e); throw e; } batch.clear(); } } }

六、性能对比(实测 10 万条数据)

方案耗时CPU内存可靠性
单条插入1200+ 秒90%+低(易超时)
批量插入(无分块)45 秒60%极高(OOM 风险)
分块 + 批量 + 流式读取5.2 秒40%

📌提速 200 倍以上!


七、高级优化技巧

1️⃣ 临时关闭索引(仅限 MyISAM 或 InnoDB 大量导入)

-- 导入前 ALTER TABLE users DISABLE KEYS; -- 执行批量导入 -- 导入后 ALTER TABLE users ENABLE KEYS;

⚠️ InnoDB 不支持DISABLE KEYS,但可考虑先删索引,后重建(谨慎使用)。


2️⃣ 调整 MySQL 参数(需 DBA 权限)

# my.cnf innodb_buffer_pool_size = 2G # 增大缓冲池 innodb_log_file_size = 512M # 增大日志文件 bulk_insert_buffer_size = 256M # MyISAM 专用

3️⃣ 使用LOAD DATA INFILE(终极方案)

// 直接生成 CSV,调用 MySQL 命令 String sql = "LOAD DATA LOCAL INFILE '/tmp/users.csv' INTO TABLE users FIELDS TERMINATED BY ','"; jdbcTemplate.execute(sql);

速度最快(10 万条 < 1 秒),但需文件在 DB 服务器或开启local_infile


八、避坑指南

⚠️ 坑 1:忘记rewriteBatchedStatements=true

MySQL 默认不重写批量语句,batchUpdate退化为单条执行!

⚠️ 坑 2:批量太大导致max_allowed_packet超限

调整 MySQL 配置:max_allowed_packet = 64M

⚠️ 坑 3:Excel 读取用XSSFWorkbook(POI)

它会把整个文件加载到内存!必须用 EasyExcel 或 SXSSF


九、完整依赖(Maven)

<!-- EasyExcel(阿里开源,流式读取) --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency> <!-- Spring Boot JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>

十、总结:批量导入黄金法则

  1. 不要单条插入→ 用batchUpdate
  2. 不要全量加载→ 用流式读取(EasyExcel);
  3. 不要默认配置→ 开启rewriteBatchedStatements=true
  4. 不要大事务→ 每批一个事务;
  5. 监控进度→ 加日志,让用户知道“没卡死”。

记住
10 万条不是问题,100 万条也能秒级搞定——关键在“批量 + 流式 + 调优”!


视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/6 18:34:44

LOOKUP函数典型用法合集

LOOKUP函数主要用于在查找范围中查询指定的查找值&#xff0c;并返回另一个范围中对应位置的值。 她有两个特点&#xff1a; 1、要求查询区域必须升序进行排序。如果没有经过排序&#xff0c;LOOKUP函数也会认为排在数据区域最后的内容&#xff0c;是该区域中最大的。 2、当…

作者头像 李华
网站建设 2026/2/4 6:11:38

Java程序员如何深入学习Spring源码?

金三银四也快要到了&#xff0c;不知道大家最近面试的时候有没有被问到过Spring相关问题&#xff08;循环依赖、事务、生命周期、传播特性、IOC、AOP、设计模式、源码&#xff09;&#xff1f;拿Spring来说&#xff0c;现在面试面试官一般会直接问&#xff1a;谈一下你对Spring…

作者头像 李华
网站建设 2026/2/7 14:15:11

HTTP 请求方法选择与 RESTful 实践(对比 GraphQL、RPC)

HTTP请求方法在实际开发中并非仅使用POST&#xff0c;但确实存在简化使用现象。 早期因技术限制&#xff08;如浏览器表单仅支持GET/POST&#xff09;和简化思维导致过度使用POST。 现代开发推荐RESTful风格&#xff1a;GET查询、POST创建、PUT/PATCH更新、DELETE删除&#xff…

作者头像 李华
网站建设 2026/2/8 11:28:40

AI 驱动人才管理落地难?Moka 全流程解决方案助力企业破局

在数字化转型浪潮下&#xff0c;企业对人力资源管理的效率与精准度要求不断提升&#xff0c;智慧人力信息系统逐渐成为企业管理的重要工具。很多 HR 从业者和企业管理者想了解智慧人力信息系统的具体定义与价值&#xff0c;也希望找到实现 AI 驱动全流程人才管理的有效路径。本…

作者头像 李华
网站建设 2026/2/5 4:46:32

便携式移动气象监测设备

便携式移动气象监测设备设计与实现 一、设计背景与意义 气象监测在农业生产、环境治理、科研勘探、应急救援等领域至关重要&#xff0c;传统气象监测设备体积庞大、依赖固定站点、部署成本高&#xff0c;难以满足移动观测与临时监测需求。现有便携气象设备多存在参数测量单一…

作者头像 李华
网站建设 2026/2/8 19:22:35

便携式信号发生器

便携式信号发生器设计与实现 一、设计背景与意义 信号发生器作为电子测量、电路调试、教学实验的核心工具&#xff0c;广泛应用于电子工程、通信技术、科研实验等领域。传统台式信号发生器存在体积庞大、依赖市电、操作复杂等问题&#xff0c;难以满足户外现场调试、移动设备维…

作者头像 李华