oracle中批量插入应避免单条executeupdate()循环,因其事务开销大、易触发游标超限;优先用addbatch()+executebatch()并配置oracle特有参数,超10万行宜改用sql*loader等方案。

为什么不能直接用 executeUpdate() 循环插入
单条 executeUpdate() 插入在 Oracle 中会触发完整事务开销:每次都要走网络往返、解析 SQL、分配游标、写 redo log。1000 条数据可能耗时数秒,且容易触发 Oracle 的 ORA-01000: maximum open cursors exceeded 错误——尤其当 PreparedStatement 没有显式关闭或复用时。
关键不是“能不能”,而是“代价太高”。批量插入的核心目标是减少 round-trip 次数和游标占用。
addBatch() + executeBatch() 是基础但不够稳
Oracle JDBC 驱动对标准批处理支持有限,默认行为仍是逐条执行(尤其在旧版 ojdbc6),除非显式启用批处理模式。
- 必须设置连接参数:
connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY),避免默认的可滚动结果集拖慢性能 - 调用前务必设置批大小:
statement.setFetchSize(0)和statement.setBatchSize(100)(setBatchSize()是 Oracle 特有方法,非 JDBC 标准) - 驱动版本强烈建议用
ojdbc8(对应 JDK 8),ojdbc6对executeBatch()的底层优化几乎为零 - 遇到
BatchUpdateException时,getUpdateCounts()返回的数组可能含Statement.EXECUTE_FAILED,需按索引定位失败项,不能简单重试整批
真正高效的方案:用 OraclePreparedStatement 的 executeBatch() + setExecuteBatch()
这是 Oracle JDBC 的隐藏能力,绕过标准 JDBC 批处理的模拟逻辑,直连 Oracle 的 ARRAY DML 机制。
示例关键片段:
String sql = "INSERT INTO t_user(name, age) VALUES (?, ?)"; OraclePreparedStatement ops = (OraclePreparedStatement) conn.prepareStatement(sql); ops.setExecuteBatch(100); // 触发底层数组绑定 for (int i = 0; i
- 必须强制转型为
OraclePreparedStatement,否则setExecuteBatch()不可用 -
setExecuteBatch(n)的n建议设为 50–200:太小失去批量意义,太大易触发 Oracle 内存限制(如ORA-04030: out of process memory) - 不要混用
executeQuery()或其他非批操作在同一 PreparedStatement 上,会清空当前 batch 状态 - 该方式依赖 Oracle 服务端支持 ARRAY DML(Oracle 9i+ 默认开启,无需额外配置)
大数量插入(>10 万行)必须考虑替代路径
JDBC 再怎么优化,本质仍是行式协议,网络和序列化开销无法消除。此时应跳出 JDBC 思维:
- 导出为 CSV,用
SQL*Loader直接加载:速度通常比 JDBC 快 5–10 倍,且不占 Java 堆内存 - 用 Oracle 的
DBMS_SCHEDULER或外部表(CREATE TABLE ... ORGANIZATION EXTERNAL)对接文件系统 - 如果必须走 JDBC,考虑分段提交(如每 5000 行 commit 一次),并关闭自动提交:
conn.setAutoCommit(false),否则每批都会隐式 commit,redo 压力翻倍 - 注意 Oracle 的
ARRAYSIZE(客户端)和DB_FILE_MULTIBLOCK_READ_COUNT(服务端)参数会影响批量读写效率,但 JDBC 层不可控,只能通过 DBA 协调
批量插入的瓶颈往往不在 Java 代码,而在 Oracle 的 redo 日志生成、UNDO 表空间竞争和网络带宽。测速时一定要用真实数据量 + 开启 SET AUTOTRACE ON 看执行计划,别只看 Java 端耗时。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











