我有一个带有Oracle数据库后端的Java应用程序,我需要插入多行。我已经看过关于inserting multiple rows into Oracle的讨论,但是我也对在混合中抛出JDBC时性能如何受到影响感兴趣。
我看到了一些可能性:
选项1: 使用单行插入PreparedStatement并多次执行:
String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
stmt.setString(1, obj.getBar());
stmt.setString(2, obj.getBaz());
stmt.execute();
}
选项2: 构建Oracle INSERT ALL语句:
String insert = "INSERT ALL " +
"INTO foo(bar, baz), (?, ?) " +
"INTO foo(bar, baz), (?, ?) " +
"SELECT * FROM DUAL";
PreparedStatement stmt = conn.prepareStatement(insert);
int i=1;
for(MyObject obj : someList) {
stmt.setString(i++, obj.getBar());
stmt.setString(i++, obj.getBaz());
}
stmt.execute();
选项3: 使用PreparedStatement的addBatch功能:
String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
stmt.setString(1, obj.getBar());
stmt.setString(2, obj.getBaz());
stmt.addBatch();
}
stmt.execute();
我想另一种可能性是创建一个CSV文件并使用SQL Loader,但是我不确定如果你增加创建CSV文件的开销会真的更快......
那么哪个选项的执行速度最快?
答案 0 :(得分:9)
使用addBatch()
的{{1}}功能,用于 1,000,000行以下的任何内容。
您添加到代码中的每个附加组件都会增加依赖性和失败点。
如果沿着那条路走(外部表,sql loader等),请确保它真的值得。
将数据序列化到csv文件,将其移动到数据库可读的位置很容易花费一秒左右的时间。
在那段时间里,如果我把它吸了起来并开始使用JDBC插入,我本可以插入20,000行。
答案 1 :(得分:2)
即使没有直接路径加载,SQL Loader似乎也更好,但是很难维护。 批量插入比单个插入语句快2-4倍。 插入所有就像批量插入一样,这两者都会比PL / SQL实现更快。
您也可以阅读this AskTom主题。
答案 2 :(得分:1)
使用批处理对程序员来说是透明的。以下是here的引用:
设置连接批次值
您可以为Oracle连接中的任何Oracle预准备语句指定默认批处理值。 >为此,请使用OracleConnection对象的setDefaultExecuteBatch()方法。例如,以下代码将与conn连接对象关联的所有预准备语句对象的默认批处理值设置为20:
((的OracleConnection)康恩).setDefaultExecuteBatch(20);
即使这为连接的所有预准备语句设置了默认批处理值,也可以通过在各个Oracle预处理语句上调用setDefaultBatch()来覆盖它。
连接批处理值将应用于设置此批处理值后创建的语句对象。