2012-08-23 2 views
7

아래는 Prepared Statement를 사용하여 Oracle Database에 multiple records(around 5000-7000)을 삽입하는 데 사용하는 코드입니다.Prepared Statement를 여러 번 효율적으로 사용하기

내가 현재하고있는 방식이 좋습니다. 또는 일부는 batch thing을 사용하여 더 향상시킬 수 있습니까? 내가 사용하고 그건

pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL); 

for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) { 

    pstatement.setInt(1, entry.getKey()); 
    pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID)); 
    pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID)); 
    pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID)); 
    pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID)); 
    pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID)); 
    pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID)); 
    pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID)); 
    pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID)); 
    pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID)); 
    pstatement.executeUpdate(); 

    pstatement.clearParameters(); 
} 

업데이트되면서 코드 : -

public void runNextCommand() { 

    Connection db_connection = null; 
    PreparedStatement pstatement = null; 
    int batchLimit = 1000; 
    boolean autoCommit = false; 

    try { 
     db_connection = getDBConnection(); 

     autoCommit = db_connection.getAutoCommit(); 
     db_connection.setAutoCommit(false); //Turn off autoCommit 
     pstatement = db_connection.prepareStatement(LnPConstants.UPSERT_SQL); // create a statement 

     for (Entry<Integer, LinkedHashMap<Integer, String>> entry : GUID_ID_MAPPING.entrySet()) { 
      pstatement.setInt(1, entry.getKey()); 
      pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID)); 
      pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID)); 
      pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID)); 
      pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID)); 
      pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID)); 
      pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID)); 
      pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID)); 
      pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID)); 
      pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID)); 
      pstatement.addBatch(); 

      batchLimit--; 

      if(batchLimit == 0){ 
       pstatement.executeBatch(); 
       pstatement.clearBatch(); 
       batchLimit = 1000; 
      } 
      pstatement.clearParameters(); 
     } 

    } catch (SQLException e) { 
     getLogger().log(LogLevel.ERROR, e); 
    } finally { 
     try { 
      pstatement.executeBatch(); 
      db_connection.commit(); 
      db_connection.setAutoCommit(autoCommit); 
     } catch (SQLException e1) { 
      getLogger().log(LogLevel.ERROR, e1.getMessage(), e1.fillInStackTrace()); 
     } 

     if (pstatement != null) { 
      try { 
       pstatement.close(); 
       pstatement = null; 
      } catch (SQLException e) { 
       getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace()); 
      } 
     } 
     if (db_connection!= null) { 
      try { 
       db_connection.close(); 
       db_connection = null; 
      } catch (SQLException e) { 
       getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace()); 
      } 
     } 
    } 
} 
+0

(트랜잭션이 올바르게 사용되고 있는지 확인하십시오. 그렇지 않으면 준비된 문을 사용하여 게시 된 코드가 "좋지 않습니다", 즉 INSERT/UPDATE가 "빠름"입니다. –

답변

8

당신은 addBatch()를 사용하여 한 번에 문을 다시 실행을 생각할 수 있습니다. 또한 @pst가 귀하의 질문에 댓글을 달았으므로 을 사용해보십시오. 다음과 같이 할 것

방법은 다음과 같습니다

boolean autoCommit = connection.getAutoCommit(); 
try{ 
    connection.setAutoCommit(false //Turn off autoCommit 
    pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL); 

    int batchLimit = 1000; 

    try{ 
     for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) { 
      pstatement.setInt(1, entry.getKey()); 
      pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID)); 
      pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID)); 
      pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID)); 
      pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID)); 
      pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID)); 
      pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID)); 
      pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID)); 
      pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID)); 
      pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID)); 

      pstatement.addBatch(); 
      batchLimit--; 

      if(batchLimit == 0){ 
       pstatement.executeBatch(); 
       pstatement.clearBatch 
       batchLimit = 1000; 
      } 
      pstatement.clearParameters(); 
     } 
    }finally{ 
     //for the remaining ones 
     pstatement.executeBatch(); 

     //commit your updates 
     connection.commit(); 
    } 
}finally{ 
    connection.setAutoCommit(autoCommit); 
} 

아이디어는 특정 한계에 도달 할 경우에만 데이터베이스 업데이트를 배치 갱신에 대한 제한을 설정하고 실행하는 것입니다. 이 방법으로 데이터베이스 호출을 정의한 batchLimit 번으로 제한합니다. 이렇게하면 더 빠를 것입니다.

또한 transaction에 대한 참고로, 나는 방금 때와 방법을 언제든지 commit에 표시했습니다. 이 결정은 귀하의 요구 사항을 기반으로하기 때문에 항상 commit의 정확한 지점이 아닐 수도 있습니다. 예외가 발생할 경우 rollback을 수행 할 수도 있습니다. 그래서 결정하는 것이 좋습니다.

transaction을 사용하는 방법에 대한 더 나은 그림을 보려면 "Using Transaction" 자습서를보십시오.

+0

여기서'addBatch()'를 어떻게 사용하는지 명확하게 알 수 있도록 예제 코드를 제공 할 수 있습니까? 큰 도움이 될 것입니다. – AKIWEB

+0

@ Nevzz03 : 샘플 코드로 답변을 업데이트했습니다. 희망이 도움 :) – Sujay

+0

자세한 답변에 대한 감사합니다 Sujay.당신의 도움에 감사를 표합니다. 방금 변경 사항을 적용한 후 제안 된대로 현재 사용중인 전체 코드로 내 질문을 업데이트했습니다. 내가 모든 걸 잘하는 것처럼 보이고 나에게 잘못한 일이 없다면 알려주시겠습니까? – AKIWEB

1

코드 조각이 나에게 좋을 것 같습니다.

단지 코드 청결을 위해 이라고하는 변수에 entry.getValue()을 넣었습니다.
clearParameters()으로 전화 할 필요가 없습니다.

마지막으로 준비된 문은 더 이상 필요하지 않을 때 올바르게 처리해야합니다 (close()).

+0

제안에 대해 gd1에게 감사드립니다. 'clearParameters()'를 호출 할 필요가 없다고 생각하는 이유는 무엇입니까? 지식의 관점에서 알고 싶었습니다. – AKIWEB

+1

매개 변수를 설정하면 이전 값이 지워집니다. :) – gd1

1

예, 일괄 업데이트를 수행하면 실적이 크게 향상됩니다. 그냥 구글, 내 선호하는 대답은 this one from Mkyong.com입니다. 그렇지 않으면 코드가 괜찮아 보입니다. "clearParameters()"는 실제로 필요하지 않으며 프로세서 사이클을 소비 할 수도 있습니다. 중요 : AutoCommit이 활성화 된 경우, 이전에이를 해제하고 업데이트를 활성화하는 것을 잊지 마세요, 이것은 엄청난 개선을 가져옵니다.

PS

위 추천은 내 경험에 기반합니다. 나는 방금이 질문에 이미 here at Stackoverflow을 묻고 그 대답은 매우 자세하다는 것을 지적했다. PreparedStatements 및 일괄 처리에 대한 자세한 내용은 오라클 문서 here과 트랜잭션 (AutoCommit) here에 나와 있습니다.

관련 문제