2010-06-12 17 views
15

मैं एक आवेदन की विलंबता के संवेदनशील हिस्से पर काम कर रहा हूँ, मूल रूप से मैं एक नेटवर्क घटना डेटा को बदलने और उसके बाद डीबी में सभी डेटा सम्मिलित प्राप्त होगा। प्रोफाइलिंग के बाद मैं देखता हूं कि मूल रूप से मेरा पूरा समय डेटा को बचाने की कोशिश कर रहा है।उच्च प्रदर्शन हाइबरनेट सम्मिलित

Save: 27 
Commit: 9 

Save: 27 
Commit: 9 

Save: 26 
Commit: 9 

Save: 36 
Commit: 9 

Save: 44 
Commit: 0 

यह मेरे लिए भ्रामक है: यहाँ कोड

private void insertAllData(Collection<Data> dataItems) 
{ 
    long start_time = System.currentTimeMillis(); 
    long save_time = 0; 
    long commit_time = 0; 
    Transaction tx = null; 
    try 
    { 
     Session s = HibernateSessionFactory.getSession(); 
     s.setCacheMode(CacheMode.IGNORE); 
     s.setFlushMode(FlushMode.NEVER); 
     tx = s.beginTransaction(); 
     for(Data data : dataItems) 
     { 
      s.saveOrUpdate(data); 
     } 
     save_time = System.currentTimeMillis(); 
     tx.commit(); 
     s.flush(); 
     s.clear(); 
    } 
    catch(HibernateException ex) 
    { 
     if(tx != null) 
      tx.rollback(); 
    } 
    commit_time = System.currentTimeMillis(); 
    System.out.println("Save: " + (save_time - start_time)); 
    System.out.println("Commit: " + (commit_time - save_time)); 
    System.out.println(); 
} 

संग्रह के आकार हमेशा 20. कम से कम यहाँ है समय डेटा है कि मैं देख रहा है। मुझे लगता है कि save त्वरित होना चाहिए और हर समय commit पर खर्च किया जाना चाहिए। लेकिन स्पष्ट रूप से मैं गलत हूँ। मैंने लेनदेन को हटाने की भी कोशिश की है (यह वास्तव में जरूरी नहीं है) लेकिन मैंने खराब समय देखा ... मैंने hibernate.jdbc.batch_size = 20 सेट किया है ...

मैं 500 से अधिक संदेश/सेकंड प्राप्त करने की उम्मीद कर सकता हूं तो मुझे 20 मिलीसेकंड से कम होने के लिए एकल संदेश हैंडलिंग की आवश्यकता है।

मैं इस ऑपरेशन की जरूरत होने के लिए जितनी जल्दी हो सके, आदर्श वहाँ केवल डेटाबेस के लिए एक गोल यात्रा होगी। मैं यह कैसे कर सकता हूँ?

+0

बीटीडब्लू, क्या आपको 'फ्लशमोड # कभी नहीं' का उपयोग करते समय 'फ्लश()' के बाद 'प्रतिबद्ध() 'माना जाना चाहिए? –

+0

@ पास्कल थिवेंट। मुझे नहीं पता :-) – luke

+1

ठीक है, 'लेनदेन # प्रतिबद्ध() 'के जावडोक को पढ़ें :) –

उत्तर

13

अपनी प्राथमिक कुंजी पीढ़ी को सर्वर पक्ष ऑटो-वृद्धि से दूर ले जाएं। राउंड ट्रिप से बचने के लिए पीके पीढ़ी के लिए आपका जावा कोड ज़िम्मेदार होना चाहिए।

सभ्य थोक डालने प्रदर्शन के लिए, यदि आप एक विधि है कि saveOrUpdate को हर एक फोन पर डेटाबेस हिट करने के लिए की जरूरत नहीं होगी की जरूरत है। प्राथमिक कुंजी के रूप में यूयूआईडी का उपयोग करना, या implementing HiLo इसे प्राप्त करने में सहायता कर सकता है। अन्यथा, वास्तव में कोई थोक सम्मिलन नहीं चल रहा है।

अन्य बाहरी प्रणालियों के साथ प्रदर्शन और अंतःक्रियाशीलता दोनों के लिए, पूल या pooled-lo अनुकूलक सबसे अच्छा विकल्प हैं।

+1

मैं वर्तमान में आईडी उत्पन्न करने के लिए एक ऑरैकल अनुक्रम का उपयोग कर रहा हूं। क्या यह व्यवहार्य नहीं है? – luke

+1

यह बिल्कुल ठीक था !, मैंने अनुक्रम को हटा दिया और अनुक्रम और बाम को शुरू करने के लिए स्टार्टअप में एक क्वेरी जोड़ा, 7.5 एक्स स्पीडअप इसे मेरी दहलीज से नीचे रखता है। – luke

+0

यह सुनकर खुशी हुई :-) – Michael

3

ईमानदारी से, मुझे नहीं पता कि आपके परीक्षण और आपके द्वारा दिखाए जा रहे "उपायों" से उचित रूप से क्या निष्कर्ष निकाला जा सकता है (मुझे गर्मजोशी से बहुत अधिक उपर है, संग्रह बहुत छोटा है, और नमूना बहुत छोटा है)।

वैसे भी, मैं आपको बता सकता है कि अपने वर्तमान कोड स्केल नहीं होगा और आप बहुत संभावना है जब एक बड़ा संग्रह गुजर सत्र में विस्फोट हो जा रहे हैं। आपको नियमित अंतराल पर सत्र को फ्लश और साफ़ करने की आवश्यकता होती है (यदि बैच आकार 20 है तो प्रत्येक 20 रिकॉर्ड)।

वास्तव में, मैं पूरे Chapter 13. Batch processing पढ़ने की सलाह।

+0

मैं ऊपर दिए गए कोड में सत्र को फ़्लशिंग और समाशोधन कर रहा हूं। संग्रह 20 से अधिक कभी नहीं होंगे – luke

0

कुछ बुनियादी सामान:

  • आप चलाता है, या कोई सूचकांक के साथ विदेशी कुंजी की कमी है?
  • क्या आपके पास बैचिंग ड्राइवर हैं?
  • बैच मोड (hibernate.jdbc.batch_size पास्कल संदर्भ से देखें) में अपने ड्राइवरों हैं?
  • आपकी तालिकाओं पर कोई अनुक्रमणिका (यदि आपके पास बहुत सारे इंडेक्स हैं, तो कभी-कभी इसे सम्मिलित करना धीमा हो सकता है)?

बैचिंग जेडीबीसी 2.0 का हिस्सा है, यह आपको 'बैच' में कई कथन निष्पादित करने की अनुमति देता है; विचार राउंड ट्रिप विलंबता को कम करना है (आप प्रति लेनदेन एकाधिक बैच निष्पादित कर सकते हैं)।

Statement stmt = dbCon.createStatement("insert into DataTable values (?,?,?)"); 
stmt.setInt(1, x1); stmt.setInt(2, x2), stmt.setString(3, "some value"); 
stmt.addBatch(); 
... 
stmt.setInt(1, x2); stmt.setInt(2, x3), stmt.setString(3, "some other value"); 
stmt.addBatch(); 

stmt.executeBatch(); 
dbCon.commit(); 

आप शायद इसे बेंचमार्क परीक्षण के रूप में उपयोग कर सकते हैं। मैं एसक्यूएल को भी देखता हूं जो जेनरेट करता है, यह देखने के लिए कि क्या यह उत्पन्न आईडी प्राप्त करने के लिए प्रति सम्मिलित क्वेरी कर रहा है या नहीं।

+1

मैं कैसे बता सकता हूं कि मेरे पास बैचिंग ड्राइवर है या नहीं? – luke

संबंधित मुद्दे