2012-08-23 13 views
7

Di seguito è riportato il codice che sto utilizzando per inserire multiple records(around 5000-7000) nel database Oracle utilizzando l'istruzione preparata.Utilizzo dell'istruzione preparata più volte in modo efficiente

Il modo in cui sto facendo attualmente è buono? O può essere migliorato di più usando un po 'di 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(); 
} 

Codice Udpated che sto usando: -

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

(Assicurarsi che le transazioni vengano utilizzate correttamente, altrimenti il ​​codice pubblicato "non sarà buono", anche [ri] usando le istruzioni preparate., Ovvero INSERT/UPDATE è "veloce". COMMIT è "lento".) –

risposta

8

si può pensare di utilizzare addBatch() e l'esecuzione di una schiena di dichiarazioni in un solo colpo. Inoltre, come @pst ha commentato nella tua domanda, considera l'utilizzo di .

Il modo in cui si farebbe è la seguente:

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); 
} 

L'idea è di impostare un limite per gli aggiornamenti batch ed eseguire un aggiornamento del database solo quando si raggiunge un limite particolare. In questo modo stai limitando una chiamata al database una volta ogni batchLimit che hai definito. In questo modo sarebbe più veloce.

Nota anche per il transaction, ho appena mostrato come e quando a commit. Questo potrebbe non essere sempre il punto corretto per commit perché questa decisione sarebbe basata sul tuo requisito. Si potrebbe anche voler eseguire un rollback in caso di un'eccezione. Quindi tocca a te decidere.

Dai un'occhiata al tutorial "Using Transaction" per avere una migliore immagine di come usare transaction.

+0

Potete fornirmi una base di esempio sul mio codice in modo da ottenere un'immagine chiara su come usare 'addBatch()' qui? Sarà di grande aiuto. – AKIWEB

+0

@ Nevzz03: aggiornata la mia risposta con un codice di esempio. Spero che questo aiuti :) – Sujay

+0

Grazie Sujay per la risposta dettagliata.Apprezzato il tuo aiuto. Ho appena aggiornato la mia domanda con il codice completo che sto usando attualmente come suggerito da voi dopo aver apportato le modifiche. Puoi dare un'occhiata e fammi sapere se ti sembra tutto a posto e non sto facendo niente di sbagliato? – AKIWEB

1

Il tuo codice mi sembra buono.

Solo per la pulizia del codice, inserisco entry.getValue() in una variabile (chiamiamola value).
E non è necessario chiamare clearParameters().

Infine, ricordarsi di disporre correttamente l'istruzione preparata quando non ce n'è più bisogno (close()).

+0

Grazie a gd1 per i suggerimenti. Perché pensi che non sia necessario chiamare 'clearParameters()'? Volevo solo sapere dal punto di vista della conoscenza. – AKIWEB

+1

Quando si imposta un parametro, il valore precedente viene cancellato. :) – gd1

1

Sì, l'esecuzione di aggiornamenti batch migliorerebbe significativamente le prestazioni. Solo google per questo, la mia risposta preferita è this one from Mkyong.com. Altrimenti, il tuo codice sembra ok. "clearParameters()" non è realmente necessario, potrebbe anche consumare alcuni cicli del processore. Importante: se AutoCommit è stato abilitato, non dimenticare di disabilitarlo prima, e abilitarlo dopo aver eseguito gli aggiornamenti, questo porta di nuovo un enorme miglioramento.

PS

Sopra raccomandazione è basata anche sulla mia esperienza. Ho appena notato che questa domanda era già stata richiesta here at Stackoverflow e la risposta è molto dettagliata. Ulteriori informazioni su PreparedStatements e batch sono disponibili nei documenti Oracle here e su Transactions (AutoCommit) here.

Problemi correlati