必须启用rewritebatchedstatements=true参数,否则executebatch()仅表面批量实则单条发送;开启后驱动自动重写为多值insert,3000条插入耗时从4000ms降至400ms。

Java 中批量数据库操作的性能瓶颈,往往不在代码逻辑本身,而在于 JDBC 与 MySQL 之间的通信方式。默认情况下,executeBatch() 并不会真正合并 SQL,而是把每条语句单独发给数据库——看起来是“批量”,实际仍是“单条轮询”。要让批处理真正生效,关键一步就是开启 MySQL Connector/J 的批处理重写功能。
必须启用 rewriteBatchedStatements=true
这是最直接、见效最快的优化手段。它让驱动在客户端自动将多条 INSERT 语句重写成一条带多个 VALUES 的语句,大幅减少网络往返和服务器解析开销。
- 连接 URL 中添加参数:
&rewriteBatchedStatements=true - 配套关闭服务端预编译(避免冲突):
&useServerPrepStmts=false - 建议开启预编译语句缓存:
&cachePrepStmts=true - 完整示例:
jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&useServerPrepStmts=false&cachePrepStmts=true
配合合理的 batch size 控制
光开参数不够,batch size 设得太大或太小都会影响效果。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 太小(如 10–50):无法摊薄网络和事务开销,收益有限
- 太大(如 >5000):可能触发
max_allowed_packet限制,或导致单次事务过重、锁持有时间长 - 推荐范围:500~2000 条/批,具体根据单行数据大小动态调整(例如每行 200 字节,1000 行约 200KB,远低于默认 4MB 上限)
别忘了事务控制和连接池配置
批处理必须运行在显式事务中,否则每条语句仍会自动提交。
- 手动控制事务:
conn.setAutoCommit(false),执行完executeBatch()后调用conn.commit() - 连接池(如 HikariCP)需配置合理最大连接数和超时,避免批量线程阻塞等待连接
- 禁用连接池的自动提交验证(如 HikariCP 的
connection-test-query在批量期间可临时关闭)
验证是否真正生效
不能只看代码有没有调 addBatch(),要确认底层是否真的合并发送了。
- 用 Wireshark 或 MySQL 的 general_log 查看实际收到的 SQL 语句
- 开启 MySQL 慢日志并设置
long_query_time=0,观察单条 INSERT 是否变成多值形式 - 对比开启前后耗时:3000 条插入从 4000ms 降到 400ms 是典型表现
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










