PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

स्प्रिंग + हाइबरनेट:क्वेरी प्लान कैश मेमोरी उपयोग

मैंने इस मुद्दे को भी मारा है। यह मूल रूप से आपके IN क्लॉज और हाइबरनेट में उन क्वेरी योजनाओं को कैश करने की कोशिश कर रहे मानों की चर संख्या रखने के लिए उबलता है।

इस विषय पर दो बेहतरीन ब्लॉग पोस्ट हैं। पहला:

<ब्लॉकक्वॉट>

एक प्रोजेक्ट में हाइबरनेट 4.2 और MySQL का उपयोग इन-क्लॉज क्वेरी के साथ जैसे:select t from Thing t where t.id in (?)

इन पार्स किए गए एचक्यूएल प्रश्नों को हाइबरनेट कैश करता है। विशेष रूप से हाइबरनेटSessionFactoryImpl इसमें QueryPlanCache है queryPlanCache . के साथ औरparameterMetadataCache . लेकिन यह एक समस्या साबित हुई जब इन-क्लॉज के लिए मापदंडों की संख्या बड़ी और भिन्न होती है।

ये कैश प्रत्येक विशिष्ट क्वेरी के लिए बढ़ते हैं। तो 6000पैरामीटर वाली यह क्वेरी 6001 जैसी नहीं है।

इन-क्लॉज क्वेरी को संग्रह में पैरामीटर की संख्या तक विस्तारित किया गया है। मेटाडेटा को क्वेरी में प्रत्येक पैरामीटर के लिए क्वेरी प्लान में शामिल किया गया है, जिसमें x10_, x11_, आदि जैसे जेनरेट किए गए नाम शामिल हैं।

इन-क्लॉज पैरामीटर्स की संख्या में 4000 विभिन्न भिन्नताओं की कल्पना करें, इनमें से प्रत्येक में औसतन 4000 पैरामीटर हैं। प्रत्येक पैरामीटर के लिए क्वेरीमेटाडेटा जल्दी से मेमोरी में जुड़ जाता है, ढेर को भर देता है, क्योंकि यह कचरा एकत्र नहीं किया जा सकता है।

यह तब तक जारी रहता है जब तक कि क्वेरी पैरामीटरकाउंट में सभी विभिन्न विविधताओं को कैश नहीं किया जाता है या JVM हीप मेमोरी से बाहर चला जाता है और थ्रो करना शुरू कर देता हैjava.lang.OutOfMemoryError:Java हीप स्पेस।

इन-क्लॉज से बचना एक विकल्प है, साथ ही पैरामीटर (या कम से कम एक छोटे आकार) के लिए एक निश्चित संग्रह आकार का उपयोग करना है।

क्वेरी योजना कैश अधिकतम आकार को कॉन्फ़िगर करने के लिए, संपत्ति देखेंhibernate.query.plan_cache_max_size , डिफ़ॉल्ट रूप से 2048 (कई मापदंडों वाले प्रश्नों के लिए आसानी से बहुत बड़ा)।

और दूसरा (पहले से भी संदर्भित):

<ब्लॉकक्वॉट>

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

तो उच्च दरों पर उत्पन्न होने वाली नई क्वेरी से कैश थ्रैशिंग परिणाम। यह कई मुद्दों के कारण हो सकता है। मैंने देखा है कि दो सबसे आम हैं - हाइबरनेट में बग जो पैरामीटर को पारित करने के बजाय जेपीक्यूएल स्टेटमेंट में पैरामीटर को प्रस्तुत करने का कारण बनता है और "इन" - क्लॉज का उपयोग करता है।

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

दूसरा मुद्दा इस तरह से है कि हाइबरनेट "इन" क्लॉज के साथ प्रश्नों को संसाधित करता है (उदाहरण के लिए मुझे सभी व्यक्ति इकाइयां दें जिनकी कंपनी आईडीफील्ड 1, 2, 10, 18 में से एक है)। "इन" -क्लॉज में प्रत्येक अलग-अलग पैरामीटर के लिए, हाइबरनेट एक अलग क्वेरी उत्पन्न करेगा - उदाहरण के लिए select x from Person x where x.company.id in (:id0_) 1 पैरामीटर के लिए,select x from Person x where x.company.id in (:id0_, :id1_) 2पैरामीटर वगैरह के लिए। इन सभी प्रश्नों को अलग-अलग माना जाता है, जहां तक ​​​​क्वेरी प्लान कैश का संबंध है, जिसके परिणामस्वरूप फिर से कैशेथ्रैशिंग होता है। आप शायद कुछ निश्चित पैरामीटर तैयार करने के लिए उपयोगिता वर्ग लिखकर इस मुद्दे के आसपास काम कर सकते हैं - उदा। 1,10, 100, 200, 500, 1000। यदि आप, उदाहरण के लिए, 22 पैरामीटर पास करते हैं, तो यह 100 तत्वों की एक सूची लौटाएगा जिसमें 22 पैरामीटर शामिल हैं init और शेष 78 पैरामीटर एक असंभव मान पर सेट हैं (जैसे -1 आईडी के लिए) विदेशी कुंजी के लिए उपयोग किया जाता है)। मैं मानता हूं कि यह एक बदसूरत हैक है लेकिन काम पूरा कर सकता है। परिणामस्वरूप आपके कैश में अधिकतम 6 अद्वितीय प्रश्न होंगे और इस प्रकार थ्रैशिंग कम हो जाएगी।

तो आपको कैसे पता चलेगा कि आपको समस्या है? आप कुछ अतिरिक्त कोड लिख सकते हैं और कैश में प्रविष्टियों की संख्या के साथ मेट्रिक्स को उजागर कर सकते हैं उदा। जेएमएक्स पर, लॉगिंग ट्यून करें और लॉग का विश्लेषण करें, आदि। यदि आप एप्लिकेशन को संशोधित नहीं करना चाहते (या नहीं कर सकते हैं), तो आप बस ढेर को डंप कर सकते हैं और इसके खिलाफ इस ओक्यूएल क्वेरी को चला सकते हैं (उदाहरण के लिए मैट का उपयोग करके):SELECT l.query.toString() FROM INSTANCEOF org.hibernate.engine.query.spi.QueryPlanCache$HQLQueryPlanKey l से . यह आपके ढेर पर किसी भी क्वेरी प्लान कैश में वर्तमान में स्थित सभी प्रश्नों को आउटपुट करेगा। यह पता लगाना बहुत आसान होना चाहिए कि आप उपरोक्त किसी भी समस्या से प्रभावित हैं या नहीं।

जहां तक ​​प्रदर्शन प्रभाव की बात है, यह कहना मुश्किल है क्योंकि यह बहुत सारे कारकों पर निर्भर करता है। मैंने एक बहुत ही तुच्छ प्रश्न देखा है जिसके कारण एक नई HQL क्वेरी योजना बनाने में 10-20 msof ओवरहेड खर्च किया गया है। सामान्य तौर पर, अगर कहीं कैश है, तो उसके लिए एक अच्छा कारण होना चाहिए - एमिस शायद महंगा है इसलिए आपको जितना संभव हो सके चूक से बचने की कोशिश करनी चाहिए। अंतिम लेकिन कम से कम, आपके डेटाबेस को बड़ी मात्रा में अद्वितीय SQL कथनों को भी संभालना होगा - जिससे यह उन्हें पार्स कर सकता है और उनमें से प्रत्येक के लिए अलग-अलग निष्पादन योजनाएं बना सकता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. दो कॉलमों को मिलाएं और एक नए कॉलम में जोड़ें

  2. RPAD () PostgreSQL में फ़ंक्शन

  3. पोस्टग्रेज में डेटाबेस कैसे स्विच करें?

  4. SQLAlchemy कोई पासवर्ड आपूर्ति त्रुटि नहीं

  5. मैं psycopg2/पायथन डीबी एपीआई के साथ डेटाबेस लेनदेन कैसे करूं?