在 Java Sql 中执行批量准备语句在上一次迭代中花费很长时间
Execute batch of prepared statement in Java Sql taking long time during Last iteration
我正在尝试从 java 应用程序向数据库中的各种表中插入大量行。所以基本上我有一个连接,我用它创建多个 Prepare 语句。然后我通过设置准备语句的变量来准备几个插入。最后,我将每个 Prepare 语句作为 execute Batch 执行并关闭语句。
我面临的问题是,我正在对上述过程进行迭代。
我有一个 writeToDataBase() 方法,它执行上述操作,这个方法在循环中调用。因此批量插入发生了很多次。(每批包含 20 个对象)。每次插入需要大约 5 到 6 秒才能在一次迭代中进行批量插入。但在最后一次迭代中需要很长时间,大约 40 秒。
我认为这是由于上一次迭代中写入的数据所致。因此,我也更改了数据以使其轻量级,但即便如此问题仍然存在。然后我尝试禁用自动提交并手动提交。这也没有帮助。
我也改变了迭代次数。例如,
在20个计数的循环中,第20个循环会花费很多时间。所以我把它改成了 运行 5 次。但是这次第 5 次循环 运行 更长。基本上最后一个循环需要很长时间才能执行批处理。
为了检查没有内存泄漏,我还关闭了正在执行的语句。但是我无法理解为什么会这样。
下面提供了代码片段。
for(ArrayList<DocumentObject> batch : documentBatches){
DBWriter.writeToDataBase(batch);
}
public static synchronized boolean writeToDataBase(ArrayList<DocumentObject> batch) {
try {
//Prepare Statements for insertion
String insertDocumentTableSQL = "INSERT INTO TEST.DOCUMENTS values (?,?,?,?,?,?,?,?);";
PreparedStatement documentPreparedStatement = connection.prepareStatement(insertDocumentTableSQL);
String insertSentencesTableSQL = "INSERT INTO TEST.SENTENCES values (?,?,?,?,?,?);";
PreparedStatement sentencesPreparedStatement = connection.prepareStatement(insertSentencesTableSQL);
//Preparing multiple inserts to the prepare statements
for(DocumentObject docObj : batch){
documentPreparedStatement = prepareInsertsToDocumentsTable(docObj,documentPreparedStatement); //sets the '?' in the query with actual values and adds it to the batch
sentencesPreparedStatement = prepareInsertsToSentencesTable(headlineSRLDocument, sectionId,sentencesPreparedStatement);
}
//execute the preparestatements
connection.setAutoCommit(false);
long start = System.currentTimeMillis();
documentPreparedStatement.executeBatch();
sentencesPreparedStatement.executeBatch();
connection.commit();
documentPreparedStatement.close();
sentencesPreparedStatement.close();
System.out.println("time taken for Execute Statements: "+(System.currentTimeMillis()-start)/1000+" seconds" );
return true;
}
下面是控制台输出,我必须跟踪每次迭代所用的时间。
time taken for Execute Statements: 3 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 5 seconds
time taken for Execute Statements: 5 seconds
time taken for Execute Statements: 9 seconds
time taken for Execute Statements: 10 seconds
time taken for Execute Statements: 6 seconds
time taken for Execute Statements: 47 seconds <------ last iteration taking more time
我找到了答案。与其他循环相比,这基本上是因为最后一个循环正在准备更多语句并将其添加到批处理中。
我检查了这一点,通过拥有一个一致的数据集,我知道将为每个循环准备并添加到批处理中的语句的数量。以前,语句是动态生成和添加的,因此我对循环中执行的语句数量一无所知。因此,preparedStatement.executeBatch() 或数据库没有问题,正如我所推测的那样。
谢谢你帮助我。
我正在尝试从 java 应用程序向数据库中的各种表中插入大量行。所以基本上我有一个连接,我用它创建多个 Prepare 语句。然后我通过设置准备语句的变量来准备几个插入。最后,我将每个 Prepare 语句作为 execute Batch 执行并关闭语句。
我面临的问题是,我正在对上述过程进行迭代。
我有一个 writeToDataBase() 方法,它执行上述操作,这个方法在循环中调用。因此批量插入发生了很多次。(每批包含 20 个对象)。每次插入需要大约 5 到 6 秒才能在一次迭代中进行批量插入。但在最后一次迭代中需要很长时间,大约 40 秒。
我认为这是由于上一次迭代中写入的数据所致。因此,我也更改了数据以使其轻量级,但即便如此问题仍然存在。然后我尝试禁用自动提交并手动提交。这也没有帮助。
我也改变了迭代次数。例如,
在20个计数的循环中,第20个循环会花费很多时间。所以我把它改成了 运行 5 次。但是这次第 5 次循环 运行 更长。基本上最后一个循环需要很长时间才能执行批处理。
为了检查没有内存泄漏,我还关闭了正在执行的语句。但是我无法理解为什么会这样。
下面提供了代码片段。
for(ArrayList<DocumentObject> batch : documentBatches){
DBWriter.writeToDataBase(batch);
}
public static synchronized boolean writeToDataBase(ArrayList<DocumentObject> batch) {
try {
//Prepare Statements for insertion
String insertDocumentTableSQL = "INSERT INTO TEST.DOCUMENTS values (?,?,?,?,?,?,?,?);";
PreparedStatement documentPreparedStatement = connection.prepareStatement(insertDocumentTableSQL);
String insertSentencesTableSQL = "INSERT INTO TEST.SENTENCES values (?,?,?,?,?,?);";
PreparedStatement sentencesPreparedStatement = connection.prepareStatement(insertSentencesTableSQL);
//Preparing multiple inserts to the prepare statements
for(DocumentObject docObj : batch){
documentPreparedStatement = prepareInsertsToDocumentsTable(docObj,documentPreparedStatement); //sets the '?' in the query with actual values and adds it to the batch
sentencesPreparedStatement = prepareInsertsToSentencesTable(headlineSRLDocument, sectionId,sentencesPreparedStatement);
}
//execute the preparestatements
connection.setAutoCommit(false);
long start = System.currentTimeMillis();
documentPreparedStatement.executeBatch();
sentencesPreparedStatement.executeBatch();
connection.commit();
documentPreparedStatement.close();
sentencesPreparedStatement.close();
System.out.println("time taken for Execute Statements: "+(System.currentTimeMillis()-start)/1000+" seconds" );
return true;
}
下面是控制台输出,我必须跟踪每次迭代所用的时间。
time taken for Execute Statements: 3 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 4 seconds
time taken for Execute Statements: 5 seconds
time taken for Execute Statements: 5 seconds
time taken for Execute Statements: 9 seconds
time taken for Execute Statements: 10 seconds
time taken for Execute Statements: 6 seconds
time taken for Execute Statements: 47 seconds <------ last iteration taking more time
我找到了答案。与其他循环相比,这基本上是因为最后一个循环正在准备更多语句并将其添加到批处理中。
我检查了这一点,通过拥有一个一致的数据集,我知道将为每个循环准备并添加到批处理中的语句的数量。以前,语句是动态生成和添加的,因此我对循环中执行的语句数量一无所知。因此,preparedStatement.executeBatch() 或数据库没有问题,正如我所推测的那样。
谢谢你帮助我。