控制变量多次测试取平均值可清晰反映插入性能差异:单条无事务约35秒,批量+事务仅1.2秒,差距达28倍;需统一环境、禁用缓存日志、复用连接、清空表重置ID,并用general_log和show processlist验证SQL执行数量与连接活跃时间。

直接写对比测试代码,控制变量、多次运行取平均值,就能清晰看出差距。关键不是“能不能测”,而是怎么让结果真实反映底层差异。
准备统一的测试环境
避免干扰因素,所有测试必须共用同一套基础配置:
- 使用同一个数据库连接(复用 Connection,禁用自动提交)
- 插入同一张表,字段结构固定,不带触发器或外键约束
- JDBC URL 加上关键参数:rewriteBatchedStatements=true(MySQL)或 useServerPrepStmts=true
- 关闭 MyBatis 的二级缓存、禁用日志输出(如 logback 设置 level=OFF)
- 每次测试前清空表并重置自增 ID,确保起始状态一致
实现三类插入方式
每种方式都封装为独立方法,插入相同数量的数据(例如 10000 条),记录 System.nanoTime() 耗时:
- 单条执行(无事务):循环中每次 new PreparedStatement + executeUpdate,不手动 commit
- 单条执行(显式事务):setAutoCommit(false),循环插入后统一 commit
- 批量执行(PreparedStatement.addBatch):prepareStatement 复用,每 1000 条调用一次 executeBatch,最后 commit
注意:不要混用方式,比如在批量逻辑里穿插 executeUpdate;也不要让单条方式意外开启事务(检查 autocommit 状态)。
立即学习“Java免费学习笔记(深入)”;
跑多轮取平均值并观察指标
单次测试容易受 GC、CPU 抢占等影响,建议每种方式执行 5–7 次:
- 记录每次的耗时(ms)、JVM 内存峰值(可用 Runtime.getRuntime().maxMemory() 和 totalMemory() 估算)
- 开启 MySQL general_log 或慢日志,确认单条方式真发了 N 条语句,批量方式只发了 ⌈N/1000⌉ 条
- 用 show processlist 观察连接活跃时间,批量方式应明显更短
实测常见结果:10000 条数据下,单条无事务约 35 秒,批量+事务约 1.2 秒——差距可达 28 倍。
用 JMeter 或简单脚本补压测视角
如果想验证并发下的表现,可跳过手写循环,改用工具辅助:
- JMeter 配置 JDBC Request,线程组设 10 用户 × 1000 循环,分别指向不同插入接口
- 写个 Shell 脚本循环调用 Java Main 类,每次传入 mode=single 或 mode=batch 参数
- 配合 Prometheus + Grafana 监控数据库的 TPS、连接数、Innodb_row_lock_time
这样能看到批量操作在高并发时对连接池和锁资源的压力优势。



















