2012-08-23 19 views
7

नीचे कोड है जिसे मैं तैयार स्टेटमेंट का उपयोग कर ओरेकल डेटाबेस में multiple records(around 5000-7000) डालने के लिए उपयोग कर रहा हूं।तैयार वक्तव्य का उपयोग कुशलतापूर्वक कई बार कुशलतापूर्वक

जिस तरह से मैं वर्तमान में कर रहा हूं वह अच्छा है? या यह 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(); 
} 

Udpated कोड मैं उपयोग कर रहा हूँ कि: -

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 "तेज़" है। COMMIT "धीमा" है।) –

उत्तर

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 का उपयोग करने के तरीके की एक बेहतर तस्वीर प्राप्त करने के लिए।

+0

क्या आप मुझे मेरे कोड पर एक उदाहरण आधार प्रदान कर सकते हैं ताकि मुझे स्पष्ट तस्वीर मिल सके कि 'addBatch()' का उपयोग कैसे करें? यह बहुत मददगार होगा। – AKIWEB

+0

@ नेवज़03: नमूना कोड के साथ मेरा जवाब अपडेट किया गया। उम्मीद है कि यह मदद करता है :) – Sujay

+0

विस्तृत उत्तर के लिए धन्यवाद सुजय।आपकी मदद की सराहना की। मैंने अपने प्रश्न को पूर्ण कोड के साथ अपडेट किया है जिसे मैं वर्तमान में उपयोग कर रहा हूं जैसा कि परिवर्तन करने के बाद आपके द्वारा सुझाया गया है। क्या आप एक नज़र डालें और मुझे बताएं कि क्या सबकुछ आपके लिए अच्छा दिखता है और मैं कुछ भी गलत नहीं कर रहा हूं? – AKIWEB

1

कोड का आपका टुकड़ा मेरे लिए अच्छा लगता है।

बस कोड की सफाई के लिए, मैं entry.getValue() को एक चर में डाल दूंगा (इसे value पर कॉल करें)।
और clearParameters() पर कॉल करने की आवश्यकता नहीं है।

अंतिम, जब आपको इसकी आवश्यकता नहीं है तो सही ढंग से तैयार कथन का निपटान करना याद रखें (close())।

+0

धन्यवाद gd1। आपको लगता है कि 'clearParameters() 'को कॉल करने की कोई आवश्यकता नहीं है? मैं बस ज्ञान के दृष्टिकोण से जानना चाहता था। – AKIWEB

+1

जब आप पैरामीटर सेट करते हैं तो पिछला मान साफ़ हो जाता है। :) – gd1

1

हां, बैच अपडेट करने से आपके प्रदर्शन में काफी सुधार होगा। बस इसके लिए गूगल, मेरा पसंदीदा उत्तर this one from Mkyong.com है। अन्यथा, आपका कोड ठीक दिखता है। "clearParameters()" वास्तव में आवश्यक नहीं है, यह कुछ प्रोसेसर चक्र भी उपभोग कर सकता है। महत्वपूर्ण: यदि ऑटोकॉमिट सक्षम किया गया था, तो इसे पहले अक्षम करना न भूलें, और अपडेट करने के बाद इसे सक्षम करें, इससे फिर से एक जबरदस्त सुधार आता है।

पीएस

ऊपर की सिफारिश मेरे अनुभव पर भी आधारित है। मैंने अभी ध्यान दिया है कि यह प्रश्न पहले से ही here at Stackoverflow से पूछा गया था और उत्तर बहुत विस्तृत है। तैयार किए गए स्तर और बैचों पर अधिक ओरेकल दस्तावेज़ here और लेनदेन (ऑटोकॉमिट) here के बारे में पाया जा सकता है।