0

CSV ファイルから大量のデータを MSSQL Server 2008 にインポートしています。コア JDBC (ORM フレームワークなし) を使用し、Microsoft が提供するドライバー 'sqljdbc4.jar' を使用して DB と通信しています。

以下は私の要件です:

  1. CSV ファイルを順番に解析します。
  2. ビジネス要件に基づいてレコードを検証します (レコードが無効な場合は、エラー ファイルの各レコードに対してエラーを記録します)。
  3. 無効ではないレコードを DB にインポートします。(レコードが無効な場合は、エラー ファイル内の各レコードに対してエラーをログに記録します。)
  4. 成功とエラーの 2 つの結果ファイルを保存します。成功すると、同じ数のフィールドで良好なレコードが得られます。エラー ファイルには、エラーを含む 'ERROR' フィールドが 1 つ追加されます (Logged from validate / import face)。

現在、レコードを 1 つずつインポートしています。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 日の更新。

コードを変更して、1 つの CSV ファイルをインポートすると、PreparedStatement オブジェクトが 1 つだけ作成されるようにしました。新しいコードは次のとおりです。

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;

}

ありがとう。

4

1 に答える 1

3

prepareStatement入力データの各行に対して再度呼び出しているようです。これにより、を使用することによるパフォーマンスの向上がほとんどなくなりPreparedStatementます。代わりに、ループのPreparedStatement外側に を作成し、ループの内側にsetInt,setStringexecuteUpdate呼び出しのみを保持します。

于 2012-09-18T20:43:48.040 に答える