2012-08-28 16 views
14

मैं हाइबरनेट 4.1.6 का उपयोग कर रहा हूं और एक सूची बनाई गई गति के साथ समस्याएं हैं। मैं निम्नलिखित क्वेरी चला रहा हूं।हाइबरनेट क्वेरी.सूची() धीमी क्यों है?

public void doQuery(final Baz baz){ 
    final Query query = getSessionFactory().getCurrentSession().createQuery(
      "select c.id, foo.someValue from Foo as foo "+ 
      "join foo.a as a"+ 
      "join foo.b as b "+ 
      "join b.c as c "+ 
      "where baz=:baz" 
     ); 
    query.setParameter("baz", baz); 
    Long start=System.currentTimeMillis(); 
    final List<Object[]> list = query.list(); 
    Long end=System.currentTimeMillis(); 
    System.out.println((end-start)); 
} 

मैंने डेटाबेस पर भेजी गई वास्तविक क्वेरी प्राप्त करने के लिए हाइबरनेट डीबगिंग सेट की है। मैंने उस क्वेरी को सीधे डेटाबेस में चलाया और यह 0.015 एमएस में 23,000 पंक्तियां लौटा दी। तो, मैं अनुमान लगा रहा हूं कि सवाल मुद्दा नहीं है। उपरोक्त उदाहरण से पता चलता है कि उस सूची को बनाने में ~ 32 सेकंड लगते हैं। क्या ऐसा कुछ है जो इसे गति देने के लिए किया जा सकता है?

अद्यतन: मैं विधि createSQLQuery() हाइबरनेट डिबगिंग क्वेरी का उपयोग कर उपयोग करने की कोशिश है और यह बस के रूप में विधि createQuery() के रूप में धीमी गति से भाग गया।

अद्यतन: मैं एक राज्यविहीन सत्र का उपयोग करने की कोशिश की, लेकिन यह बस के रूप में धीमी गति से भाग गया।

अद्यतन: मैं कुछ आंकड़े (सही पर hibernate.generate_statistics ध्वज की स्थापना) outputted लेकिन कुछ भी मेरे लिए चौंकाने वाली लग रहा है:

Hibernate SessionFactory Statistics [ 
    Number of connection requests[4] 
    Number of flushes done on the session (either by client code or by hibernate[3] 
    The number of completed transactions (failed and successful).[3] 
    The number of transactions completed without failure[3] 
    The number of sessions your code has opened.[4] 
    The number of sessions your code has closed.[3] 
    Total number of queries executed.[4] 
    Time of the slowest query executed.[28258] 
    the number of collections fetched from the DB.[6] 
    The number of collections loaded from the DB.[6] 
    The number of collections that were rebuilt[0] 
    The number of collections that were 'deleted' batch.[0] 
    The number of collections that were updated batch.[0] 
    The number of your objects deleted.[0] 
    The number of your objects fetched.[1] 
    The number of your objects actually loaded (fully populated).[204] 
    The number of your objects inserted.[1] 
    The number of your object updated.[0] 
] 

Hibernate SessionFactory Query Statistics [ 
    total hits on cache by this query[0] 
    total misses on cache by this query[0] 
    total number of objects put into cache by this query execution[0] 
    Number of times this query has been invoked[1] 
    average time for invoking this query.[28258] 
    maximum time incurred by query execution[28258] 
    minimum time incurred by query execution[28258] 
    Number of rows returned over all invocations of this query[23303] 
] 

अद्यतन: मैं एक ही सुस्ती देखने के लिए जब एक ScrollableResults से अगले() कर एक मूल प्रश्न से। ध्यान दें कि मैं लूप में कुछ भी नहीं कर रहा हूं।

ScrollableResults results = query.scroll(); 
    Long start=System.currentTimeMillis(); 
    while (results.next()) { 
     //do nothing 
    } 
    Long end=System.currentTimeMillis(); 
    System.out.println((end-start)); 
+0

एक uncommited हो सकता है लेनदेन कार्यों को पकड़ना। –

+1

आप अपने हाइबरनेट एसक्यूएल को प्रिंट करना चाहते हैं। सबसे अधिक संभावना एक एन + 1 चयन मुद्दा है। –

+0

जॉर्डन, मुझे इस प्रश्न को धारण करने वाले किसी भी लेनदेन की जानकारी नहीं है। जॉन, मैंने उपरोक्त वर्णित एसक्यूएल मुद्रित किया और क्वेरी ठीक है। – user973479

उत्तर

7

मैं, इस जवाब पर 100% निश्चित नहीं हूँ ट्यूनिंग/अनुकूलन मुद्दों हमेशा से रहे हैं के बाद से इंगित करने के लिए इतना मुश्किल।

हालांकि, इस तथ्य के आधार पर कि आपने show_sql पर चालू किया है, क्वेरी को निकाला है, और इसे सीधे डेटाबेस के विरुद्ध चलाया है और हाइबरनेट क्वेरी के माध्यम से उप-दूसरे परिणाम बनाम निष्पादन समय देखा है, मैं जिस तरह से हाइबरनेट है query.list() कॉल के परिणामस्वरूप ऑब्जेक्ट्स का निर्माण और हाइड्रेटिंग। Simple hibernate query returning very slowly

यह वे की तरह लगता है:

यहाँ एक और उपयोगकर्ता के लिए जो हाइबरनेट में समान क्वेरी प्रदर्शन के मुद्दों का उल्लेख किया और POJO में पूर्ण सुविधा कंस्ट्रक्टर्स (कंस्ट्रक्टर्स कि प्रत्येक क्षेत्र के लिए एक मूल्य को स्वीकार) जोड़कर नाटकीय प्रदर्शन बढ़ जाती है देखा है इस फिक्स पर ठोकर खाई, और इस बारे में कोई स्पष्ट समझ नहीं थी कि यह क्यों काम करता है। गुणों का पता लगाने के लिए प्रतिबिंब का उपयोग करने के लिए हाइबरनेट के बारे में अटकलें थीं। मैं खुद उत्सुक हूं और जब मुझे मौका मिलता है तो बेहतर समझने के लिए हाइबरनेट के स्रोत कोड में खोदने की योजना बना रहा हूं। इस बीच, हालांकि, आप अपने सभी पीओजेओ वर्ग विशेषताओं के पैरामीटर के साथ इन पूर्ण कन्स्ट्रक्टर को जोड़ने और देखना चाहते हैं कि इससे कोई फर्क पड़ता है या नहीं।

मुझे पता है तुम क्या ढूँढते हैं कृपया, जैसा कि मैंने बहुत हाइबरनेट प्रदर्शन के अनुकूलन में दिलचस्पी है। धन्यवाद!

+0

हाय फिलिप, आपके उत्तर के लिए धन्यवाद ': या आप केवल एक प्रश्न देखते हैं,' हाइबरनेट साथ शुरू करना चाहिए है! मैंने उस लिंक पर एक नज़र डाली और मेरे सभी पीओजेओ के पास पूर्ण कन्स्ट्रक्टर हैं। दुर्भाग्य से यह समाधान मेरी स्थिति पर लागू नहीं होता है। – user973479

+0

हम्म, बहुत बुरा, मैं उम्मीद कर रहा था कि मदद मिलेगी। ऐसा लगता है कि आप अपनी समस्या निवारण में बहुत गहन हैं, और मैं वास्तव में मदद करना चाहता हूं। क्या आप अपने पीओजेओ पोस्ट कर सकते हैं? –

+0

दुर्भाग्यवश नहीं :( – user973479

4

(show_sql के साथ) प्रश्नों एक समस्या है ही नहीं करते, तो शायद यह कोड में है। विजुअलVM शुरू करें (जेडीके के साथ jvisualvm के रूप में आता है) और अपने सीपीयू प्रोफाइलर का उपयोग यह पता लगाने के लिए करें कि कौन से तरीके सबसे लंबे समय तक लेते हैं।

+0

यह विशेष कॉल क्वेरी.लिस्ट धीमापन के लिए अपराधी है। उम्मीद है कि किसी को क्यों इस व्यवहार होता है और संभवतः एक वैकल्पिक हल – user973479

+1

मेरा मतलब है, कि जो तरीकों में से * * query.list (द्वारा कहा जाता है) दोषी है के रूप में अंतर्दृष्टि प्रदान कर सकते हैं? हाइबरनेट कोड में डिग मूल कारण खोजने के लिए। –

+0

के रूप में जैसा कि पहले उल्लेख, वहाँ कोई भी कर रहे हैं – user973479

1

मैंने उस क्वेरी को सीधे डेटाबेस में चलाया और यह 0.015 एमएस में 23,000 पंक्तियां लौटा दी। तो, मैं अनुमान लगा रहा हूं कि सवाल मुद्दा नहीं है।

यह समयपूर्व हो सकता है, क्योंकि क्वेरी निष्पादन समय क्वेरी टेक्स्ट से बहुत अधिक पर निर्भर करता है। भले ही वे एक ही डेटा पर क्वेरी चलाए जाएं, आप कैसे जानते हैं कि डेटाबेस ने उसी निष्पादन योजना का उपयोग किया था? आप कैसे जानते हैं कि यह डिस्क कैश में कैश हिट की समान राशि प्राप्त करता है?उदाहरण के लिए, डेटाबेस से बात करते समय हाइबरनेट तैयार कथन का उपयोग करता है, लेकिन शायद आपने नहीं किया। ओरेकल में, निष्पादन योजना क्वेरी टेक्स्ट द्वारा कैश की जाती है, इसलिए एक अलग क्वेरी टेक्स्ट का मतलब ताजा गणना की गई निष्पादन योजना है। चूंकि कैश किए गए निष्पादन योजना का गठन विभिन्न क्वेरी पैरामीटर के आधार पर किया जा सकता है, यह बहुत अलग हो सकता है - और यह परिमाण के आदेशों से निष्पादन के समय को बदल सकता है। ध्यान दें कि मैं यह नहीं कह रहा हूं कि यह डेटाबेस है डेटाबेस, लेकिन मैं संभावना को छूट नहीं दूंगा।

इसलिए, आपको सबसे पहले जो करना चाहिए वह यह मापने के लिए है कि क्या डेटाबेस, या आपके जेवीएम में चल रहा कुछ भी उस समय बर्बाद हो रहा है। ऐसा करने का एक आसान तरीका JVMs cpu खपत को देखना है क्योंकि क्वेरी निष्पादित की जा रही है। यदि यह एक धागे से काफी कम है, तो JVM कुछ के लिए इंतजार कर रहा है - संभवतः डेटाबेस।

यदि यह डेटाबेस है, तो निष्पादन योजना और अन्य प्रासंगिक प्रदर्शन मीट्रिक को कैप्चर करने के लिए अपने डेटाबेस के अनुकूलन टूल का उपयोग करें।

यदि यह JVM में, एक प्रोफाइलर प्रदर्शन टोंटी इंगित करने के लिए इस्तेमाल करते हैं।

0

हम ने वही समस्या में भाग, पता नहीं अगर यह संबंधित है। की तरह मूल रूप से, के बाद से हम एक बार क्वेरी के साथ Newing नए SessionFactorys थे, यह क्या कर रहा था प्रश्नों:

select streamref0_.UUID as UUID145_, streamref0_.Tape_TapeId as Tape2_145_ from StreamRefToTape streamref0_ where streamref0_.UUID=? 

आप में बड़ी संख्या पर ध्यान देंगे। यह पता चला है कि यह प्रति नए सत्र कारखाने में एक बार बढ़ता है। वैसे भी, यह ऑरैकल को प्रत्येक प्रश्न के लिए एक नई योजना बनाने में अपना समय बिताने का कारण बन रहा था (यह बताया गया है कि सीपीयू लगभग सभी "कठिन पार्स" समय में नई योजनाएं उत्पन्न कर रहा था - मुझे लगता है कि ओरेकल योजनाओं को उत्पन्न करने में धीमा है जो उसने नहीं देखा है पहले?)। इस विशेष मामले में फिक्स केवल हर बार एक नए कारखाने का उपयोग करना था। यह भी देखें Hibernate produce different SQL for every query

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2588723819082 हार्ड पार्स बताते हैं, जो स्पष्ट रूप से खराब हैं।

एक अन्य संभावित ठीक, "कच्चे एसक्यूएल" (JDBC) या हाइबरनेट भीतर संभवतः कच्चे एसक्यूएल प्रश्नों का उपयोग करने के लिए यह है कि इस विशेष मामले किसी भी तरह से समस्या को ठीक नहीं लगता था ...

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