应使用 preparedstatement 批量执行,分批插入(每批1000–5000条),复用同一 preparedstatement 实例,关闭自动提交,显式 commit,并调用 clearbatch() 和 clearparameters() 防 ora-01000。

用 PreparedStatement + 批量执行,别用单条 executeUpdate()
单条插入十万次,基本等于卡死或超时。Oracle 对单次网络往返和解析开销敏感,必须走批量机制。核心是让 JDBC 复用同一 SQL 模板、攒够一批再发,减少 round-trip 和 SQL 解析次数。
关键操作:addBatch() 积累参数,executeBatch() 一次性提交。注意不是“一次 insert 十万行”,而是“分批,每批几千条”。
-
setAutoCommit(false)关闭自动提交,显式commit(),否则每批都隐式提交,性能暴跌 - 每批大小建议 1000–5000 条(
addBatch()调用次数),太大易 OOM 或触发 Oracle 的ORA-01000: maximum open cursors exceeded - 调用
clearBatch()在每次executeBatch()后,否则下一批会叠加旧数据
Oracle 需要启用 rewriteBatchedStatements=true 吗?不需要,那是 MySQL 的
Oracle JDBC 驱动(ojdbc8.jar 及以上)原生支持标准 JDBC 批量,不依赖 URL 参数重写 SQL。加 rewriteBatchedStatements=true 不但无效,还可能报 java.sql.SQLException: Invalid parameter binding。
真正该配的是连接池和事务相关参数:
- URL 中确保含
?useUnicode=true&characterEncoding=UTF-8(虽 Oracle 默认 UTF-8,但显式声明防乱码) - 连接池(如 HikariCP)设
connection-timeout≥ 30s,max-lifetime避免连接在长批量中过期 - 避免在循环里反复
conn.prepareStatement(sql)—— 提前 prepare 一次复用
遇到 ORA-01000: maximum open cursors exceeded 怎么办
这不是代码写错了,是 Oracle 实例级限制被批量语句意外触发:每条 PreparedStatement 占一个 cursor,如果 prepare 太多次(比如在循环里 new 多个 PS),或者批大小过大导致驱动内部缓存膨胀,就会超限。
- 严格复用同一个
PreparedStatement实例,不要在 for 循环内调用conn.prepareStatement(...) - 确认数据库参数
open_cursors(查SELECT value FROM v$parameter WHERE name = 'open_cursors'),开发环境可临时调到 2000+,但生产需评估 - 每批执行后立即
ps.clearParameters()(非必需但稳妥),并确保异常时能ps.close()+conn.rollback()
// 正确示例节选
String sql = "INSERT INTO t_user (id, name, age) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
for (int i = 0; i
<h3>比 JDBC 批量更快的方案?考虑 <code>SQL*Loader</code> 或 <code>DBMS_LOB</code>
</h3>
<p>JDBC 批量对十万条已是合理选择,但若后续要插百万/千万级,JDBC 就成了瓶颈。此时应切出 Java 进程,交给 Oracle 原生工具:</p>
-
SQL*Loader(sqlldr):把数据导成 CSV,用控制文件定义映射,速度通常是 JDBC 的 5–10 倍,且不占 JVM 内存 - Java 写入临时表 + 调用
INSERT /*+ APPEND */ INTO ... SELECT:先 bulkInsert 到临时表(用executeBatch),再用 Oracle 直接路径插入目标表 - 避免在 Java 层做复杂转换逻辑后再插 —— 能推给数据库函数(如
TO_DATE、DECODE)的,就别在 Java 里SimpleDateFormat
十万条这个量级,只要批大小合适、连接稳定、没额外 ORM 封装,JDBC 批量 3–8 秒能完成。慢下来往往是因为开了 Hibernate 的 show_sql、启用了全字段日志、或数据库归档模式未调优。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











