2016-04-13 5 views
1

私は、テキストファイル(各レコードはタブで区切られています)からEmployeeデータをArrayListに読み込む必要があります。次に、この従業員オブジェクトをリストからDBのEmployeeテーブルに挿入する必要があります。このために、リスト要素を1つずつ繰り返し、従業員の詳細をDBに1つずつ挿入します。この方法は、100kを超えるレコードを持つことができず、データ全体を挿入するのに非常に時間がかかるため、パフォーマンスを向上させることはお勧めできません。パフォーマンスを向上させるためにマルチスレッドを使用してListからDBテーブルにデータを挿入するにはどうすればよいですか?

パフォーマンスを向上させるためにリストからデータをdbに挿入する際に、ここでマルチスレッドを使用する方法を教えてください。また、このシナリオを最適化するために、CountDownLatchクラスとExecutorServiceクラスを使用する方法もあります。

ReadWriteTest

public class ReadWriteTest { 

public static void main(String... args) { 
    BufferedReader br = null; 
    String filePath = "C:\\Documents\\EmployeeData.txt"; 
    try { 
     String sCurrentLine; 
     br = new BufferedReader(new FileReader(filePath)); 
     List<Employee> empList = new ArrayList<Employee>(); 

     while ((sCurrentLine = br.readLine()) != null) { 
      String[] record = sCurrentLine.split("\t"); 
      Employee emp = new Employee(); 
      emp.setId(record[0].trim()); 
      emp.setName(record[1].trim()); 
      emp.setAge(record[2].trim()); 
      empList.add(emp); 
     } 
     System.out.println(empList); 

     writeData(empList); 

    } catch (IOException | SQLException e) { 
     e.printStackTrace(); 
    } 
} 

public static void writeData(List<Employee> empList) throws SQLException { 
    Connection con =null; 
    try{ 
     Class.forName("oracle.jdbc.driver.OracleDriver"); 

     con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","system","oracle"); 
     for(Employee emp : empList) 
     { 
     PreparedStatement stmt=con.prepareStatement("insert into Employee values(?,?,?)"); 
     stmt.setString(1,emp.getId()); 
     stmt.setString(2,emp.getName()); 
     stmt.setString(3,emp.getAge()); 
     stmt.executeUpdate(); 
     }   
     }catch(Exception e){ 
      System.out.println(e); 
     } 
     finally{ 
      con.close(); 
     } 
     } 
} 

Employeeクラス

public class Employee { 

String id; 
String name; 
String age; 

public String getId() { 
    return id; 
} 
public void setId(String id) { 
    this.id = id; 
} 
public String getName() { 
    return name; 
} 
public void setName(String name) { 
    this.name = name; 
} 
public String getAge() { 
    return age; 
} 
public void setAge(String age) { 
    this.age = age; 
} 
@Override 
public String toString() { 
    return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]"; 
} 
} 

EmployeeData.txt

1 Sachin 20 
2 Sunil 30 
3 Saurav 25 

答えて

2

ダイレクトインポート

Javaアプリケーションのアプローチの代わりに、データベースアプローチがあります。すべての主要データベースには、テキストファイルから直接テーブルにデータをインポートできるツールがあります。

Postgresには、COPYコマンドがあります。これはrun from the command lineまたはSQL内から可能です。説明はthe wiki pageを参照してください。

データベースツールセットを見てください。

+0

をはい、Postgresの 'COPY'のようなインポートツールを実行するために高速で非常に*することができます。データは、SQLステートメントを処理することなく、テーブルに直接供給されます。これらのツールは通常、処理や変更の機能をほとんど提供しないため、インポートするデータはターゲットテーブルの構造と厳密に一致しなければならないという制約があります。プログラマとして私はプログラミング言語(Javaなど)を超えて考えることを学び、Postgresのような価値のあるデータベースプラットフォームで利用できる強力な機能を活用しています。 –

0

アプリケーションによっては、DBアップデートコードをメインアプリケーションスレッドのスレッドに入れておくとよいでしょう。たとえば、Executorsを使用してこれを行うことができます。

代わりにbatch updatesを使用して調べることもできます。

複数のスレッドでDBを更新しようとすると、DBがアトミック性を維持する必要があるため、すべてのテーブルを一度に1つのスレッドでしか更新できないため、処理速度が向上しない可能性があります。

は、あなたは本当に夢中になるとJava 8のCompletableFutureを使用して、メインスレッドのオフ両方の操作を行うことができます:

CompletableFuture.supplyAsync(new Supplier<List<Employee>>() 
{ 
    @Override 
    public List<Employee> get() 
    { 
     List<Employee> employees = new ArrayList<>(); 
     // get employee list 
     return employees; 
    } 
}).thenAcceptAsync(new Consumer<List<Employee>>() 
{ 
    @Override 
    public void accept(List<Employee> employees) 
    { 
     // put into DB using batching 
    } 
}); 

最初supplyAsyc別のスレッドで指定されたコードを呼び出します。処理が完了すると、戻り値はthenAcceptAsyncConsumerに渡され、その関数は別のスレッドでも実行されます。私は@kuporificに同意

CompletableFuture.supplyAsync(() -> { 
    List<Employee> employees = new ArrayList<>(); 
    // get employee list 
    return employees; 
}).thenAcceptAsync(employees -> { 
    // put into DB using batching 
}); 
1

:として

これは、よりコンパクトに書き込むことができます。バッチ更新は、パフォーマンスの観点からは優れていることがわかります。

は、あなたのコードに次のよう編集して試してみて:

public static void writeData(List<Employee> empList) throws SQLException { 
    Connection con =null; 
    final int BATCH_SIZE = 1000; // just an indicative number 
    try{ 
     Class.forName("oracle.jdbc.driver.OracleDriver"); 
     con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","system","oracle"); 
     Statement statement = con.createStatement(); 
     int counter = 0; 
     for(Employee emp : empList) 
     { 
      String query = "insert into Employee (id, name, city) values('" 
        emp.getId() + "','" + emp.getName() + "','" + emp.getAge() + "')"; 
      statement.addBatch(query); 
      if (counter % BATCH_SIZE == 0){ 
       statement.executeBatch(); 
      } 
      counter++; 
     } 

     statement.close(); 

     }catch(Exception e){ 
      System.out.println(e); 
     } 
     finally{ 
      con.close(); 
     } 
} 
関連する問題