Oracle JDBC驱动版本必须匹配数据库大版本,ojdbc8.jar或ojdbc11.jar支持Server-Side Batch优化,旧版ojdbc6.jar导致executeBatch性能差;需关闭自动提交、设合理batchSize(1000~5000)、调用setFetchSize(0),并手动commit且检查返回值。
Oracle JDBC驱动版本必须匹配数据库大版本
用错驱动是批量插入慢的隐形元凶。jdbc 4.2(对应 ojdbc8.jar)对 oracle 12c+ 的 executebatch 有关键优化,比如支持服务器端批处理(server-side batch),而老版 ojdbc6.jar 默认走客户端模拟,每条语句仍发一次网络包。
- Oracle 19c/21c → 强制用
ojdbc8.jar(JDK 8+)或ojdbc11.jar(JDK 11+) - 确认方式:运行
System.out.println(oracle.jdbc.driver.OracleDriver.getMajorVersion()),输出应为8或11 - 别信 Maven 仓库里标“universal”的旧包——它可能只是重命名的 ojdbc6
addBatch前必须关闭自动提交且预设batchSize
默认 autoCommit=true 会让每次 executeBatch() 都触发完整事务提交,彻底废掉批量意义;而没设 setFetchSize() 或没控制单批行数,容易触发 Oracle PGA 内存溢出或 ORA-04030 错误。
-
connection.setAutoCommit(false)是硬性前提,否则addBatch只是假批量 - 单批 size 控制在 1000~5000 行之间(视单行数据大小调整),超 10000 行易触发 Oracle 内部缓冲区切换开销
- 显式调用
statement.setFetchSize(0)(对 Oracle 有效),避免 JDBC 驱动额外拉取元数据
executeBatch后必须手动commit且检查返回值
很多人只调 executeBatch() 就以为完事,结果事务卡在连接里没提交,或者某条失败了却没感知——Oracle 批量执行是“全成功”或“全失败”,但 JDBC 返回的是 int[],其中 Statement.EXECUTE_FAILED 表示该位置语句失败,不是抛异常。
- 必须紧跟
connection.commit(),别依赖连接池自动回收时的 close - 检查返回数组:
for (int i = 0; i - 若需部分成功(如跳过脏数据),得改用
PreparedStatement+ 单条 executeUpdate,别硬扛 batch
批量插入字段多时优先用 INSERT ALL 而非重复VALUES
当单条记录字段超过 10 个,用传统 INSERT INTO t(a,b,c) VALUES(?,?,?) 拼 1000 条,Oracle 解析 SQL 的 CPU 开销会反超网络传输。换成 INSERT ALL 一条语句塞多行,能显著降低硬解析次数。
- 写法示例:
INSERT ALL INTO t(a,b) VALUES(?,?) INTO t(a,b) VALUES(?,?) SELECT * FROM DUAL - 注意:Oracle 对
INSERT ALL单语句最大支持约 1000 个 INTO 子句,超了要拆批 - 不能用在有触发器或自增列(IDENTITY)的表上——它绕过某些约束校验逻辑
批量性能卡点从来不在代码行数,而在 JDBC 驱动行为、事务边界和 Oracle 内部执行路径的咬合。少一个 setAutoCommit(false),或者驱动版本差一级,吞吐量就掉一个数量级。这些细节不报错,但慢得毫无征兆。
立即学习“Java免费学习笔记(深入)”;











