2012-08-23 33 views
7

Hazırlanmış Deyimi kullanarak Oracle Veritabanına multiple records(around 5000-7000) eklemek için kullanıyorum kod aşağıdadır.Hazırlanan Bildirimi birden çok kez verimli kullanma

Şu anda yapmakta olduğum yol iyi mi? Ya da bazı batch thing kullanarak daha fazla geliştirilebilir? Ben kullanıyorum olduğunu

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

udpated Kodu: -

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

(İşlemlerin doğru bir şekilde kullanıldığından emin olun. Aksi takdirde, gönderilen deyimler kullanılarak "yeniden yazılan" kodun "iyi olmayacağı" belirtilir. Bu, INSERT/UPDATE "hızlı" olur. COMMIT "yavaş" şeklindedir.) –

cevap

8

Sen addBatch() kullanarak ve tek seferde tabloların bir geri yürütülmesi düşünebilirsiniz. Ayrıca, @pst, sorunuzda yorumlandığı gibi, 'u kullanmayı düşünün. aşağıdaki gibi yapacağını

yoludur:

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

fikri belirli bir sınıra ulaştığında sadece veritabanı güncellemesi toplu güncellemeleri için bir limit tespit ve yürütmektir. Bu şekilde, tanımladığınız her bir batchLimit numarasına bir kez bir veritabanı görüşmesini sınırlandırıyorsunuz. Bu şekilde daha hızlı olurdu.

Ayrıca transaction için not, ben sadece nasıl ve ne zaman commit için gösterilmiştir. Bu her zaman commit için doğru nokta olmayabilir, çünkü bu karar sizin gereksinimlerinize dayanacaktır. Bir istisna durumunda da rollback gerçekleştirmek isteyebilirsiniz. Yani karar vermek size kalmış.

transaction'un nasıl kullanıldığına dair daha iyi bir resim elde etmek için "Using Transaction" eğiticisine bir göz atın.

+0

Kodumda örnek bir temel oluşturabilir misiniz? Böylece burada 'addBatch() 'işlevini nasıl kullanacağımı anlatabildim mi? Çok yardımcı olacak. – AKIWEB

+0

@ Nevzz03: Cevabımı örnek kod ile güncellendi. Umarım bu yardımcı olur :) – Sujay

+0

Detaylı cevap için teşekkürler Sujay.Yardımınız için teşekkür ederiz. Sorguyu, değişiklik yaptıktan sonra sizin tarafınızdan önerilen şu anda kullandığım tam kodla güncelledim. Her şey size iyi görünüyorsa ve yanlış bir şey yapmıyorum diye bir göz atabilir ve bana haber verebilir misiniz? – AKIWEB

1

Kod parçanız bana iyi görünüyor.

Sadece kod temizliği için entry.getValue() değişkenini bir değişkene koyardım (value olarak adlandırın).
Ayrıca clearParameters() numaralı telefonu aramanıza gerek yoktur.

Son olarak, hazırlanan deyimi artık ihtiyacınız olmadığında doğru şekilde atmayı unutmayın (close()).

+0

Öneriler için teşekkürler gd1. Neden clearParameters() 'aramaya gerek olmadığını düşünüyorsunuz? Sadece bilgi açısından bilmek istedim. – AKIWEB

+1

Bir parametre ayarladığınızda, önceki değer silinir. :) – gd1

1

Evet, toplu güncelleştirme yapmak performansınızı önemli ölçüde artıracaktır. Bunun için sadece google, tercih ettiğim cevap this one from Mkyong.com. Else, kodun iyi görünüyor. "clearParameters()" gerçekten gerekli değildir, hatta bazı işlemci döngülerini tüketebilir. Önemli: AutoCommit etkinleştirildiyse, daha önce devre dışı bırakmayı ve güncellemeleri yaptıktan sonra etkinleştirmeyi unutmayın, bu da büyük bir iyileştirme sağlar. Öneri Üstü

PS

deneyimlerime de dayanmaktadır. Ben sadece bu soruyu zaten here at Stackoverflow sordu ve cevabın çok ayrıntılı olduğunu kaydettim. PreparedStatements ve gruplar hakkında daha fazla bilgi için Oracle docs here ve Transactions (AutoCommit) here'da bulunabilir.

İlgili konular