2011-07-27 24 views
2

Oracle Clob列を更新するために次のコードを使用しました。パフォーマンステストの後、文字列の長さが130000を超えている間に200ms以上消費する必要があることが報告されました。それを改善するために?Oracle Clobの更新中にパフォーマンスを改善する方法は?

private void updateClobDetailsField(Map<Integer, String> idToDetails){ 
    long s1 = System.currentTimeMillis(); 
    Connection conn = null; 
    PreparedStatement pStmt = null; 
    ResultSet rset = null; 
    Map<Integer, Clob> idToDetailsClob = new HashMap<Integer, Clob>(); 
    int BATCH_SIZE = CMType.BATCH_UPDATE_MAXSIZE; 
    try 
    { 
     conn = getConnection(); 
     ServerAdapter adapter = ServerAdapter.getServerAdapter(); 

     List<Integer> IDList = new ArrayList<Integer>(); 
     for(Integer id : idToDetails.keySet()){ 
      IDList.add(id); 
     } 

     List<Integer> tempIDList = new ArrayList<Integer>(IDList); 
     while(!tempIDList.isEmpty()){ 
       int size = tempIDList.size() < BATCH_SIZE ? tempIDList.size() : BATCH_SIZE; 
       List<Integer> currentBatch = tempIDList.subList(0, size); 
       String inClause = SQLHelper.prepareInClause("ID",currentBatch.size()); 
       pStmt = conn.prepareStatement("SELECT ID, DETAILS FROM PROGRAM_HISTORY WHERE " + inClause); 
       for(int i = 0; i < currentBatch.size(); i++){ 
        pStmt.setInt(i+1, (currentBatch.get(i))); 
       } 
       rset = pStmt.executeQuery(); 
       while(rset.next()){ 
        int id = rset.getInt(1); 
        Clob detailsClob = rset.getClob(2); 
        Writer writer = adapter.getCharacterOutputStream(detailsClob); 
        String details = idToDetails.get(id); 
        if (details != null) { 
         writer.write(details); 
        } 
        writer.flush(); 
        writer.close(); 
        idToDetailsClob.put(id, detailsClob); 
       } 
       currentBatch.clear(); 
       BaseSQLHelper.close(pStmt, rset); 
     } 

     int counter = 0; 
     pStmt = conn.prepareStatement("UPDATE PROGRAM_HISTORY SET DETAILS = ? WHERE ID = ?"); 

     for(int i=0; i<IDList.size(); i++){ 
      int index = 1; 
      Clob detailsClob = (Clob) idToDetailsClob.get(IDList.get(i)); 
      pStmt.setClob(index++, detailsClob); 
      pStmt.setInt(index++, IDList.get(i)); 
      pStmt.addBatch(); 
      counter++; 
      if(counter % BATCH_SIZE == 0) { 
       pStmt.executeBatch(); 
       pStmt.clearBatch(); 
       counter = 0; 
      } 
     } 
     if(IDList.size() % BATCH_SIZE > 0) { 
      pStmt.executeBatch(); 
     }       
    } 
    catch (SQLException se) 
    { 
     se.printStackTrace(); 
    } 
    catch (IOException se) 
    { 
     se.printStackTrace(); 
    } 
    finally 
    { 
     cleanup(conn, pStmt, null); 
    } 
    System.out.println(System.currentTimeMillis()-s1); 
} 
+1

私はあなたのサーバーに関してこのJavaがどこで動作しているのか分かりませんが、それほど悪くないようです。 10メガビットの接続を想定すると、最初にこの量のデータをサーバーに取得するのにほとんどの時間が必要になります。あなたはおそらくより良いつながりを持っているかもしれませんが、物事を見通しにするのはおそらくです – GolezTrol

答えて

2

あなたのコードを正しく理解している場合は、details clob列にテキストを追加しています。

PL/SQLで実行すると、ネットワーク経由でclobをフェッチする必要がなくなるため、処理が高速になります。

DECLARE 
    l_details CLOB; 
BEGIN 
    SELECT details INTO l_details FROM program_history WHERE ID = ?; 
    dbms_lob.append(l_details, ?); 
END; 

をしてcurrentBatch.get(i)idToDetails.get(id)をバインド:たとえば、あなたは、この文を準備することができます。

PL/SQLで追加の更新は必要ありません。

0

更新可能なResultSetを使用してクエリを実行すると、別々の更新文を実行せずにスクロールしながらデータを更新できます。

resultSetConcurrencyをResultSet.CONCUR_UPDATABLEに設定してcreate your prepared statementにする必要があります。 clobデータを処理するさまざまな方法については、ストリームを扱う際のoracle documentationを参照してください。

関連する問題