簡體   English   中英

如何提高使用JDBC的數據庫導入的性能?

[英]How to improve the performance of DB import using JDBC?

我正在從CSV文件中將大量數據導入MSSQL Server2008。我正在使用核心JDBC(沒有任何ORM框架),並使用Microsoft提供的驅動程序“ sqljdbc4.jar”與DB通信。

以下是我的要求:

  1. 順序分析CSV文件。
  2. 根據業務需求驗證記錄(如果記錄無效,則將錯誤記錄到錯誤文件中的每個記錄中。)
  3. 將未發現無效的記錄導入DB。 (如果記錄無效,則將錯誤記錄到錯誤文件中的每個記錄中。)
  4. 保存兩個結果文件成功與錯誤。 成功將擁有數量相同且記錄良好的字段。 錯誤文件將在錯誤中附加一個字段“ ERROR”(從驗證/導入面記錄)。

截至目前,正在逐一導入記錄。 即使正在使用PreparedStatement,也要花費大量時間。

我沒有使用批量導入,因為我需要將確切的錯誤記錄到錯誤文件中。

請提出一個在不犧牲准確的錯誤記錄的情況下提高性能的想法。 而且我被迫在沒有任何ORM工具的情況下執行此操作。

這是示例代碼:

for (Map<String, String> csvRecord : csvAsList) {
    // Prepare category object using csvRecord.
    // invoke obj.insert(category);
}

public Category insert(Category category){

if (category == null) {
   return null;
}

String SQL = "INSERT INTO t1(c1,c2) VALUES(?,?)";
PreparedStatement pstmt = null;
ResultSet rs = null;

try {

   pstmt = this.dbConnectionUtil.getConnection().prepareStatement(SQL,
           Statement.RETURN_GENERATED_KEYS);

   pstmt.setInt(1, category.getField1());
   pstmt.setString(2, category.getField2());

   int result = pstmt.executeUpdate();

   if (result < 1) {
      return null;
   }

   rs = pstmt.getGeneratedKeys();
   if (rs.next()) {
      category.setId(rs.getInt(1));
   }

} finally {
   if (rs != null)
      rs.close();
   if (pstmt != null)
      pstmt.close();
   this.dbConnectionUtil.closeConnection();
}

return category;

}

2012年9月20日更新。

我已經修改了代碼,以便導入一個CSV文件,將只創建一個PreparedStatement對象。 新代碼如下:

public void importCSV(){
   // Create a db connection if its null or closed.
   // Create PreparedStatement objects for selects and inserts if null or closed.

   for (Map<String, String> csvRecord : csvAsList) {
      // Prepare category object using csvRecord.
      // Check whether category exists in by.
      // Import files can have up to 1,00,000 records so tracking errors is critical.
      try{
         categoryDAO.findByName(categoryName,<PreparedStatement object>);
      }
      catch(Exception exp){
         // log this to error.csv file
      }
      // If its a new category import it to the db.
      try{   
         categoryDAO.insert(category,<PreparedStatement object>);
      }
      catch(Exception exp){
         // log this to error.csv file
      }
   }

   // Close PreparedStatement objects
   // Close DB Connection

}

public Category insert(Category category,PreparedStatement pstmt ) throws SQLException{

if (category == null) {
   return null;
}

ResultSet rs = null;
try {

   pstmt.setInt(1, category.getField1());
   pstmt.setString(2, category.getField2());

   int result = pstmt.executeUpdate();

   if (result < 1) {
      return null;
   }

   rs = pstmt.getGeneratedKeys();
   if (rs.next()) {
      category.setId(rs.getInt(1));
   }

} finally {
   if (rs != null)
      rs.close();
}
return category;

}

謝謝。

似乎您正在為輸入數據的每一行再次調用prepareStatement 這幾乎可以消除使用PreparedStatement獲得的性能提升。 而是在循環外部創建PreparedStatement ,並在循環內部僅保留setIntsetStringexecuteUpdate調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM