2010-02-09 9 views
16

मैं एक विधि insert() लिखा है जो मैं एक MySQL डेटाबेस में पांच लाख रिकॉर्ड डालने के लिए JDBC बैच का उपयोग करने के कोशिश कर रहा हूँ में:JDBC बैच सम्मिलित OutOfMemoryError

public void insert(int nameListId, String[] names) { 
     String sql = "INSERT INTO name_list_subscribers (name_list_id, name, date_added)"+ 
        " VALUES (?, ?, NOW())"; 
     Connection conn = null; 
     PreparedStatement ps = null; 

     try{ 
      conn = getConnection(); 
      ps = conn.prepareStatement(sql); 

      for(String s : names){ 
       ps.setInt(1, nameListId); 
       ps.setString(2, s); 
       ps.addBatch(); 
      } 

      ps.executeBatch(); 

     }catch(SQLException e){ 
      throw new RuntimeException(e); 
     }finally{ 
      closeDbResources(ps, null, conn); 
     } 
    } 

लेकिन जब भी मैं इस विधि चलाने का प्रयास, मैं निम्नलिखित त्रुटि मिलती है: यदि मैं ps.executeUpdate() साथ ps.addBatch() की जगह

java.lang.OutOfMemoryError: Java heap space 
    com.mysql.jdbc.ServerPreparedStatement$BatchedBindValues.<init>(ServerPreparedStatement.java:72) 
    com.mysql.jdbc.ServerPreparedStatement.addBatch(ServerPreparedStatement.java:330) 
    org.apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.java:171) 

और ps.executeBatch() निकालने के लिए, यह ठीक काम करता है, हालांकि यह कुछ समय लगता है। अगर आपको पता है कि बैच का उपयोग इस स्थिति में उचित है, तो कृपया मुझे बताएं, और यदि ऐसा है, तो यह OurOfMemoryError क्यों देता है?

धन्यवाद

उत्तर

40

addBatch और executeBatch आपको बैच आवेषण करने के लिए तंत्र प्रदान करते हैं, लेकिन आपको अभी भी बैचिंग एल्गोरिदम स्वयं करने की आवश्यकता है।

यदि आप बस एक ही बैच में प्रत्येक कथन को ढेर करते हैं, तो आप मेमोरी से बाहर हो जाएंगे। आपको प्रत्येक n रिकॉर्ड बैच निष्पादित/साफ़ करने की आवश्यकता है। n का मान आपके ऊपर है, जेडीबीसी आपके लिए यह निर्णय नहीं ले सकता है। बैच आकार जितना बड़ा होगा, तेज़ चीजें चली जाएंगी, लेकिन बहुत बड़ी होगी और आपको स्मृति भुखमरी मिल जाएगी और चीजें धीमा हो जाएंगी या असफल हो जाएंगी। यह निर्भर करता है कि आपके पास कितनी मेमोरी है।

1000 के बैच आकार के साथ शुरू करें, उदाहरण के लिए, और वहां से विभिन्न मूल्यों के साथ प्रयोग करें।

final int batchSize = 1000; 
int count = 0; 
for(String s : names) { 
    ps.setInt(1, nameListId); 
    ps.setString(2, s); 
    ps.addBatch(); 

    if (++count % batchSize == 0) { 
     ps.executeBatch(); 
     ps.clearBatch(); //not sure if this is necessary 
    } 
} 
ps.executeBatch(); // flush the last few records. 
5

यह स्मृति से बाहर है क्योंकि यह स्मृति में सभी लेन-देन पकड़ और केवल यह डेटाबेस के लिए पर भेजने के लिए जब आप executeBatch कहते हैं।

आप इसे की जरूरत नहीं है परमाणु होने की और बेहतर प्रदर्शन प्राप्त करना चाहते हैं, तो आप एक प्रति रखने के लिए और executeBatch फोन रिकॉर्ड के हर n संख्या कर सकते हैं।

+0

और एन का मूल्य क्या होना चाहिए? – craftsman

+3

मूल्य आपके ऊपर है, आपको स्मृति और प्रदर्शन के बीच व्यापार बंद करने के लिए सर्वोत्तम मूल्य प्राप्त करने के लिए अपने एप्लिकेशन को बेंचमार्क करना होगा। –