基于Spring Batch 2.7.8与MySQL 8的大平文件分批读取入库性能优化求助
320万行平文件批量入库性能优化方案
数据库端优化
- 临时关闭唯一索引校验:唯一索引会随数据量增大导致插入时的冲突检查耗时暴增。InnoDB可以先执行
SET UNIQUE_CHECKS=0;和SET FOREIGN_KEY_CHECKS=0;,全量插入完成后再执行SET UNIQUE_CHECKS=1;和SET FOREIGN_KEY_CHECKS=1;,重建索引的开销远小于逐行校验的累积耗时。 - 调优批量插入参数:把MySQL的
max_allowed_packet调至64M或更高,避免大批次插入被截断。同时将JdbcTemplate的批量大小从默认值提升到500-1000,减少和数据库的交互次数。 - 大事务批量提交:不要每批都提交事务,比如每处理10000行再提交一次,降低事务日志刷盘的频率。记得手动关闭自动提交:
connection.setAutoCommit(false);,批量插入完成后再执行commit()。
文件处理与并发控制
- 控制异步线程数:CompletableFuture开太多线程会导致CPU上下文切换和数据库连接池竞争,线程数设为CPU核心数的2-4倍,或者和数据库连接池的最大连接数匹配,避免资源耗尽。
- 流式读取文件:别一次性把全量数据加载到内存,用
BufferedReader逐行读取处理,减少内存占用和GC频繁触发的性能损耗。 - 拆分处理链路:把文件读取、数据预处理、数据库插入拆成独立环节,用线程池做并行预处理,但插入环节要控制并发数,避免数据库行锁/表锁竞争。
JdbcTemplate使用优化
- 用高效的批量更新API:优先使用带
BatchPreparedStatementSetter的batchUpdate方法,复用预编译语句,减少SQL解析开销,示例代码:
jdbcTemplate.batchUpdate("INSERT INTO your_table(col1, col2) VALUES(?, ?)", new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { YourData item = batchList.get(i); ps.setString(1, item.getCol1()); ps.setString(2, item.getCol2()); } @Override public int getBatchSize() { return batchList.size(); } });
MySQL内核参数调优
- 提升缓存与日志配置:把
innodb_buffer_pool_size设为服务器内存的50%-70%,让更多索引和数据缓存在内存;调大innodb_log_file_size至2G,减少日志切换次数;如果业务允许,设置innodb_flush_log_at_trx_commit=2,降低事务日志刷盘的IO压力。 - 优化磁盘IO:如果磁盘IO是瓶颈,换成SSD存储,或者将数据文件和事务日志文件分别部署到不同物理磁盘,避免IO竞争。
内容的提问来源于stack exchange,提问作者dew025
相关产品推荐
相关产品推荐

