批量插入需分批提交以避免锁表、日志膨胀、内存溢出和超时失败;推荐每批1000~5000条,依场景选小(500)、中(2000)、大批(10000+),并配合数据库调优。

为什么批量插入要分批提交
单次插入大量数据时,如果把所有SQL放在一个事务里执行,容易触发数据库锁表、日志膨胀、内存溢出或超时失败。尤其在MySQL的InnoDB引擎中,事务越大,undo log和redo log占用越多,回滚段压力大,主从同步延迟也可能加剧。分批提交能平衡性能与稳定性,让资源占用更平滑。
合理批次大小怎么定
没有固定值,需结合实际环境测试。一般建议从1000~5000条起步尝试:
- 小批量(如500条):适合高并发写入场景,减少锁持有时间,但网络往返和事务开销略高
- 中批量(如2000条):多数OLTP系统较均衡的选择,兼顾吞吐与可控性
- 大批量(如10000+):仅适用于离线导入、低峰期ETL等场景,需确认数据库配置(如innodb_log_file_size、max_allowed_packet)是否支撑
可先用EXPLAIN FORMAT=JSON或慢日志分析单条INSERT耗时,再推算批次上限;上线前务必在预发环境压测验证。
代码层实现分批的关键点
避免简单for循环逐条提交,也不要把全部数据一次性加载进内存再切片。推荐方式:
- 流式读取源数据(如JDBC的ResultSet.setFetchSize()、Python的cursor.fetchmany()),边读边处理
- 每累积满一批,显式开启事务→执行批量INSERT(用INSERT INTO ... VALUES (...),(...),...语法)→提交→清空缓存
- 捕获异常后,记录当前批次起始偏移,支持断点续插,而非全量重试
- Java中可用JdbcTemplate.batchUpdate(),Python可用executemany(),但注意它们默认不自动分事务,仍需外层控制提交粒度
数据库侧配合调优建议
光靠应用层分批不够,还需适配数据库配置:
- 调大innodb_buffer_pool_size(建议设为物理内存50%~75%),减少磁盘IO
- 临时关闭唯一键/外键检查(SET FOREIGN_KEY_CHECKS=0、SET UNIQUE_CHECKS=0),导入完成后再开启
- 使用LOAD DATA INFILE替代INSERT(若数据在服务端文件中),速度通常快5~10倍
- 确保表无过多二级索引,非必要字段索引可在导入后重建










