Oracle和JDBC性能:INSERT ALL vs preparedStatement.addBatch

时间:2011-02-04 19:15:59

标签: oracle jdbc performance

我有一个带有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文件的开销会真的更快......

那么哪个选项的执行速度最快?

3 个答案:

答案 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()来覆盖它。

     

连接批处理值将应用于设置此批处理值后创建的语句对象。