Mri*_*moy 30 java bulkinsert resultset prepared-statement
我试图用Java填充一个带有大约50,000行10列的结果集,然后使用batchExecute方法将它们插入到另一个表中PreparedStatement.
为了使这个过程更快,我做了一些研究,发现在将数据读入resultSet时,fetchSize起着重要的作用.
拥有一个非常低的fetchSize可能导致太多的服务器访问,并且非常高的fetchSize可以阻止网络资源,所以我尝试了一点,并设置了适合我的基础设施的最佳大小.
我正在读取此resultSet并创建插入语句以插入到另一个数据库的另一个表中.
像这样的东西(只是一个样本,而不是真正的代码):
for (i=0 ; i<=50000 ; i++) {
statement.setString(1, "a@a.com");
statement.setLong(2, 1);
statement.addBatch();
}
statement.executeBatch();
Run Code Online (Sandbox Code Playgroud)
在批量更新(50,000行10列)时,使用可更新ResultSet或PreparedStaement批量执行是否更好?
seh*_*seh 46
我将依次解决您的问题.
这可能因每个JDBC驱动程序而异,但我研究的少数几个将迭代每个批处理条目,并将每个参数与准备好的语句句柄一起发送到数据库以便执行.也就是说,在上面的示例中,将使用50,000对参数执行50,000个预处理语句,但这些50,000个步骤可以在较低级别的"内循环"中完成,这是节省时间的地方.相当拉伸的类比,就像从"用户模式"退出到"内核模式"并在那里运行整个执行循环.您可以为每个批次条目节省潜入和退出该较低级别模式的成本.
您通过在执行批处理之前推送50,000个参数集来隐式定义它Statement#executeBatch().批量大小为1也同样有效.
考虑在批量插入之前显式打开事务,然后提交它.不要让数据库或JDBC驱动程序在批处理中的每个插入步骤周围强加事务边界.您可以使用该Connection#setAutoCommit(boolean)方法控制JDBC层.首先将连接从自动提交模式中取出,然后填充批次,启动事务,执行批处理,然后通过提交事务Connection#commit().
这个建议假定您插入不会并发作家百家争鸣,并假定这些事务边界会给你在插入使用源表中读取充分一致的值.如果不是这样的话,那就赞成正确而不是速度.
ResultSet或PreparedStatement批量执行是否更好?没有什么比使用您选择的JDBC驱动程序更好的测试,但我希望后者PreparedStatement- Statement#executeBatch()并将在这里胜出.语句句柄可以具有关联的列表或"批处理参数"数组,每个条目是在调用Statement#executeBatch()和Statement#addBatch()(或Statement#clearBatch())之间提供的参数集.每次调用时列表都会增长,addBatch()直到你打电话才会刷新executeBatch().因此,Statement实例实际上充当了参数缓冲区; 你是为了方便而交易内存(使用Statement实例代替你自己的外部参数设置缓冲区).
同样,只要我们不讨论特定的 JDBC驱动程序,您应该将这些答案视为一般和推测.每个驱动程序的复杂程度各不相同,每个驱动程序的优化程度各不相同.
Boh*_*ian 15
批次将"一次性完成" - 这就是你要求它做的事情.
在一次通话中尝试50,000似乎有点大.我会将其分解为1000个较小的块,如下所示:
final int BATCH_SIZE = 1000;
for (int i = 0; i < DATA_SIZE; i++) {
statement.setString(1, "a@a.com");
statement.setLong(2, 1);
statement.addBatch();
if (i % BATCH_SIZE == BATCH_SIZE - 1)
statement.executeBatch();
}
if (DATA_SIZE % BATCH_SIZE != 0)
statement.executeBatch();
Run Code Online (Sandbox Code Playgroud)
50,000行不应超过几秒钟.