Java 两种JDBC查询批处理方法中哪一种更快?
我正在尝试在一个有数百万条记录的表上使用rownum以多批方式运行update语句 第一种方法是将所有查询批处理在一起,然后运行Java 两种JDBC查询批处理方法中哪一种更快?,java,oracle,jdbc,batch-processing,Java,Oracle,Jdbc,Batch Processing,我正在尝试在一个有数百万条记录的表上使用rownum以多批方式运行update语句 第一种方法是将所有查询批处理在一起,然后运行executeBatch()方法,如下所示 for (i = num; i < limit; i += num) { String query = "update Table set someColumn ='T' where rownum<=" + i; preparedStatement = dbConnection.prepareSta
executeBatch()
方法,如下所示
for (i = num; i < limit; i += num) {
String query = "update Table set someColumn ='T' where rownum<=" + i;
preparedStatement = dbConnection.prepareStatement(query);
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
dbConnection.commit();
for(i=num;i
逻辑原因:
除非提交大小的高水位线超过服务器的日志限制(在这种情况下,事务将在部分完成后回滚),否则您可能希望所有语句都成功完成,或者全部失败。要解开部分数据库更新要困难得多,而且(取决于您的情况)如果只有一些更新成功,则可能会使数据处于不一致的状态
性能原因:
允许DB优化对一个命令的解析,协调所有活动,只启动一个事务,只进行一次提交。对同一准备语句的不同绑定变量使用批处理:
String query = "update Table set someColumn ='T' where rownum<=?";
preparedStatement = dbConnection.prepareStatement(query);
for (i = num; i < limit; i += num) {
preparedStatement.setInt(1, num);
count = preparedStatement.addBatch();
}
preparedStatement.executeBatch();
dbConnection.commit();
String query=“update Table set someColumn='T'其中rownum
有人能解释一下为什么会这样吗
这里有许多不同的东西可以优化:
所做的工作由JDBC/ODBC驱动程序和db引擎来准备和实现
解析语句
客户端和数据库服务器之间的往返通信量
数据库引擎打开和关闭(即提交)所做的工作
(或回滚)事务
您的示例正在优化不同的内容:
- 通过使用绑定参数(如第二个示例中所示),您只需
准备一次报表,这样可以减少
ODBC/JDBC驱动程序,可能还有数据库引擎
- 通过减少批处理的执行频率(第一个示例),可以减少
客户端和服务器之间的往返次数
- 通过减少提交次数(再次出现第一个示例),您减少了提交次数
数据库需要打开和关闭事务的次数
正如您所发现的,瓶颈原来是打开和关闭事务的开销。多次往返也没有帮助。这些比不使用绑定参数成本更高
幸运的是,在本例中,您可以优化这三件事。您可以使用绑定参数,一次性将所有命令发送到数据库,并执行一次提交。请参阅Jean de Lavarene的答案
但请注意行为上的变化:如果在单个批中提交,一个错误将导致批中的所有内容回滚。这可能正是您想要的,但如果不是,这些考虑因素可能优先于性能。:“频繁提交(…)让你慢下来,是的,没错,让你慢下来--让你跑得更慢”。为什么不在一条语句中更新所有内容?这很可能会更快。而且第一个循环无论如何都是错误的。在第一次迭代中,它更新1行,在第二次迭代中,它更新2行,然后是3行,然后是4行,最后是所有“限制”行。这没有任何意义。您至少应该在其中添加一个,其中somecolumn'T'
,作为well@above,我必须提到,在我的产品概念证明查询中,有一个where条件,为了简单起见,这里我删除了这些条件。
String query = "update Table set someColumn ='T' where rownum<=?";
preparedStatement = dbConnection.prepareStatement(query);
for (i = num; i < limit; i += num) {
preparedStatement.setInt(1, num);
count = preparedStatement.addBatch();
}
preparedStatement.executeBatch();
dbConnection.commit();