pgsql-प्रदर्शन सूची पर इस सप्ताह की लौ युद्ध एक बार फिर इस तथ्य के इर्द-गिर्द घूमती है कि PostgreSQL के पास अन्य डेटाबेस में पारंपरिक संकेत सिंटैक्स उपलब्ध नहीं है। इसके पीछे कई तकनीकी और व्यावहारिक कारण हैं:
- संकेत देना बाद की समस्याओं का एक सामान्य स्रोत है, क्योंकि किसी विशेष मामले में एक बार क्वेरी स्थान को ठीक करना बहुत मजबूत तरीका नहीं है। जैसे-जैसे आपका डेटा सेट बढ़ता है, और संभवतः वितरण में भी बदलाव आता है, वैसे-वैसे आपने जिस विचार की ओर संकेत किया था, वह एक छोटा विचार बन सकता है।
- एक उपयोगी संकेत इंटरफ़ेस जोड़ने से अनुकूलक कोड जटिल हो जाएगा, जिसे बनाए रखना काफी कठिन है। पोस्टग्रेएसक्यूएल काम करता है और साथ ही यह चल रहे प्रश्नों का एक कारण है क्योंकि फील-गुड कोड ("हम अपने विक्रेता तुलना फीचर सूची पर इशारा कर सकते हैं!") जो वास्तव में खुद के लिए भुगतान नहीं करता है, डेटाबेस बनाने के मामले में इसके निरंतर रखरखाव को उचित ठहराने के लिए पर्याप्त बेहतर, नीति द्वारा खारिज कर दिया गया है। यदि यह काम नहीं करता है, तो इसे जोड़ा नहीं जाएगा। और जब निष्पक्ष रूप से मूल्यांकन किया जाता है, तो संकेत एक समाधान के बजाय औसतन एक समस्या होते हैं।
- जिस तरह की समस्याएं काम करने का संकेत देती हैं, वे ऑप्टिमाइज़र बग हो सकती हैं। पोस्टग्रेएसक्यूएल समुदाय उद्योग में किसी अन्य की तुलना में तेजी से अनुकूलक में वास्तविक बग का जवाब देता है। आस-पास पूछें और आपको बग की रिपोर्ट करने वाले और इसे देखने वाले को अगले दिन तक ठीक करने से पहले कई PostgreSQL उपयोगकर्ताओं से मिलने की ज़रूरत नहीं है।
अब, संकेतों का पता लगाने के लिए मुख्य पूरी तरह से मान्य प्रतिक्रिया गायब है, आम तौर पर डीबीए से जो उनका उपयोग किया जाता है, "अच्छी तरह से जब मैं इसमें भाग लेता हूं तो मैं एक ऑप्टिमाइज़र बग को कैसे संभाल सकता हूं?" आजकल के सभी तकनीकी कार्यों की तरह, एक खराब क्वेरी समस्या के सामने आने पर सबसे तेज़ संभव समाधान पाने के लिए आमतौर पर बहुत बड़ा दबाव होता है।
यदि PostgreSQL के पास उस स्थिति से निपटने के कुछ तरीके नहीं हैं, तो कोई गंभीर उत्पादन PostgreSQL डेटाबेस नहीं होगा। . अंतर यह है कि इस डेटाबेस में आप जिन चीजों को समायोजित करते हैं, वे उन निर्णयों को प्रभावित करने में अधिक निहित हैं जो ऑप्टिमाइज़र पहले से ही काफी सूक्ष्म तरीके से करता है, बजाय इसके कि आप यह बताएं कि क्या करना है। ये शब्द के शाब्दिक अर्थ में संकेत हैं, उनके पास यह संकेत देने के लिए कुछ उपयोगकर्ता इंटरफ़ेस नहीं है कि PostgreSQL के लिए नए अन्य डेटाबेस के उपयोगकर्ता खोज रहे हैं।
इसे ध्यान में रखते हुए, आइए एक नज़र डालते हैं कि क्या है आप खराब क्वेरी योजनाओं और अनुकूलक बग के आसपास काम करने के लिए PostgreSQL में कर सकते हैं, विशेष रूप से वे चीजें जो बहुत से लोगों को लगता है कि केवल संकेतों के साथ हल की जा सकती हैं:
- join_collapse_limit: यह समायोजित करता है कि ऑप्टिमाइज़र के पास एकाधिक तालिकाओं में शामिल होने को पुन:व्यवस्थित करने के लिए कितना लचीलापन है। आम तौर पर यह हर संभव संयोजन की कोशिश करता है जब जुड़ने को पुनर्व्यवस्थित किया जा सकता है (जो कि ज्यादातर समय होता है, जब तक कि आप बाहरी जुड़ाव का उपयोग नहीं कर रहे हों)। join_collapse_limit को कम करके, शायद 1 तक भी, इस लचीलेपन में से कुछ या सभी को हटा देता है। इसे 1 पर सेट करने के साथ, आप उस क्रम में शामिल होंगे, जिस क्रम में आपने उन्हें लिखा था, अवधि। बड़ी संख्या में जुड़ने की योजना बनाना अनुकूलक के लिए सबसे कठिन कामों में से एक है; प्रत्येक जॉइन अनुमानों में त्रुटियों को बढ़ाता है, और क्वेरी प्लानिंग समय बढ़ाता है। यदि आपके डेटा की अंतर्निहित प्रकृति यह स्पष्ट करती है कि किस क्रम में शामिल होना चाहिए, और आप इसे कभी बदलने की उम्मीद नहीं करते हैं, तो एक बार जब आप सही क्रम का पता लगा लेते हैं तो आप इस पैरामीटर का उपयोग करके इसे लॉक कर सकते हैं।
- random_page_cost: 4.0 के लिए डिफ़ॉल्ट, यह पैरामीटर सेट करता है कि डिस्क पर एक यादृच्छिक पृष्ठ खोजने के लिए डिस्क की तलाश करना 1.0 के संदर्भ मान के सापेक्ष कितना महंगा है। अब, वास्तव में, यदि आप नियमित हार्ड ड्राइव पर यादृच्छिक से अनुक्रमिक I/O के अनुपात को मापते हैं, तो आप पाएंगे कि यह संख्या 50 के करीब है। तो 4.0 क्यों? पहला, क्योंकि इसने सामुदायिक परीक्षण में बड़े मूल्यों से बेहतर काम किया है। दूसरा, कई मामलों में विशेष रूप से इंडेक्स डेटा को मेमोरी में कैश किया जाएगा, जिससे उन मूल्यों को पढ़ने की प्रभावी लागत कम हो जाएगी। यदि, उदाहरण के लिए, आपका इंडेक्स 90% RAM में कैश्ड है, तो इसका मतलब है कि आप उस ऑपरेशन का 10% समय करेंगे जो 50X जितना महंगा है; जो आपकी प्रभावी random_page_cost को लगभग 5 बना देगा। इस तरह की वास्तविक दुनिया की स्थिति यही है कि डिफ़ॉल्ट समझ में आता है कि यह कहां है। मैं आम तौर पर लोकप्रिय इंडेक्स को मेमोरी में> 95% कैश प्राप्त करता हूं। यदि आपकी अनुक्रमणिका वास्तव में RAM में होने की तुलना में बहुत अधिक है, तो random_page_cost को कम करके 1.0 से ठीक ऊपर करना एक उचित विकल्प हो सकता है, यह दर्शाने के लिए कि यह किसी भी अन्य पढ़ने की तुलना में अधिक महंगा नहीं है। उसी समय, वास्तव में व्यस्त सिस्टम पर यादृच्छिक खोज उस अपेक्षा से कहीं अधिक महंगी हो सकती है जो आपको केवल एकल-उपयोगकर्ता सिमुलेशन को देखने से होती है। जब योजनाकार गलत अनुमान लगा रहा था कि वे कितने महंगे होंगे, तो डेटाबेस को इंडेक्स का उपयोग बंद करने के लिए मुझे random_page_cost को 60 तक सेट करना पड़ा। आमतौर पर वह स्थिति योजनाकार की ओर से संवेदनशीलता अनुमान त्रुटि से आती है-यदि आप किसी तालिका के लगभग 20% से अधिक स्कैन कर रहे हैं, तो योजनाकार जानता है कि अनुक्रमिक स्कैन का उपयोग करना इंडेक्स स्कैन की तुलना में बहुत अधिक कुशल होगा। बदसूरत स्थिति जहां मुझे उस व्यवहार को उस व्यवहार से बहुत पहले होने के लिए मजबूर करना पड़ा, जब योजनाकार को 1% पंक्तियों को वापस करने की उम्मीद थी, लेकिन यह वास्तव में 15% के करीब था।
- work_mem: यह समायोजित करता है कि सॉर्टिंग, हैशिंग और इसी तरह के मेमोरी-आधारित संचालन करने वाली क्वेरी के लिए कितनी मेमोरी उपलब्ध है। यह प्रश्नों के लिए केवल एक मोटा दिशानिर्देश है, कठिन सीमा नहीं है, और एक क्लाइंट क्वेरी चलाते समय work_mem के गुणकों का उपयोग कर समाप्त कर सकता है। तदनुसार, आपको सावधान रहने की आवश्यकता है कि इस मान को postgresql.conf फ़ाइल में बहुत अधिक सेट न करें। इसके बजाय आप क्या कर सकते हैं, हालांकि, यह एक क्वेरी चलाने से पहले इसे सेट करता है जो वास्तव में सॉर्टिंग या हैश डेटा रखने के लिए अतिरिक्त मेमोरी होने से लाभान्वित होता है। आप कभी-कभी इन प्रश्नों को log_min_duration_statement का उपयोग करके धीमे लॉगिंग से प्राप्त कर सकते हैं। आप उन्हें log_temp_files को चालू करके भी ढूंढ सकते हैं, जो हर बार वर्क_मेम के बहुत छोटे होने पर लॉग हो जाएगा, और इसलिए मेमोरी में होने के बजाय डिस्क पर छँटाई संचालन छँटाई।
- OFFSET 0: PostgreSQL सबक्वेरी को एक जॉइन के रूप में पुनर्व्यवस्थित करेगा, इसलिए वह इसे ऑप्टिमाइज़ करने के लिए नियमित जॉइन ऑर्डर लॉजिक का उपयोग कर सकता है। कुछ मामलों में, यह निर्णय वास्तव में खराब हो सकता है, क्योंकि लोग जिस तरह की चीजें सबक्वायरी के रूप में लिखते हैं, वह किसी कारण से अनुमान लगाना थोड़ा अधिक कठिन लगता है (मैं कहता हूं कि इस तरह की परेशानी वाले प्रश्नों की संख्या के आधार पर मुझे दिखाई देता है)। इस तर्क को रोकने के लिए आप जो एक डरपोक चाल कर सकते हैं, वह है OFFSET 0 सबक्वेरी के अंत में। यह किसी भी परिणाम को नहीं बदलता है, लेकिन OFFSET को निष्पादित करने के लिए उपयोग किए जाने वाले सीमा क्वेरी नोड के प्रकार को सम्मिलित करने से पुनर्व्यवस्था को रोका जा सकेगा। इसके बाद सबक्वेरी हमेशा उसी तरह से निष्पादित होगी जिस तरह से अधिकांश लोग इसकी अपेक्षा करते हैं-अपने स्वयं के पृथक क्वेरी नोड के रूप में।
- enable_seqscan, enable_indexscan, enable_bitmapscan: तालिका में पंक्तियों को देखने के लिए इन सुविधाओं में से किसी एक को बंद करना उस प्रकार के स्कैन से बचने की अत्यधिक अनुशंसा करने के लिए काफी बड़ा हथौड़ा है (हमेशा इसे रोकना नहीं-यदि आपकी योजना को निष्पादित करने का कोई तरीका नहीं है लेकिन एक seqscan, पैरामीटर बंद होने पर भी आपको एक seqscan मिलेगा)। मुख्य बात यह है कि मैं इनके लिए सलाह देता हूं कि प्रश्नों को ठीक न करें, यह EXPLAIN के साथ प्रयोग करना है और यह देखना है कि दूसरे प्रकार के स्कैन को क्यों पसंद किया गया था।
- enable_nestloop, enable_hashjoin, enable_mergejoin: अगर आपको संदेह है कि आपकी समस्या तालिकाओं को पढ़ने के तरीके के बजाय शामिल होने का प्रकार है, तो इनमें से किसी एक पैरामीटर का उपयोग करके अपनी योजना में दिखाई देने वाले प्रकार को बंद करने का प्रयास करें, फिर EXPLAIN चलाएं दोबारा। संवेदनशीलता अनुमानों में त्रुटियां आसानी से जुड़ने को कम या ज्यादा कुशल बना सकती हैं जो वास्तव में है। और, फिर से, यह देखना कि वर्तमान शामिल होने के तरीके के साथ योजना कैसे बदलती है, यह इस बात के लिए बहुत जानकारीपूर्ण हो सकता है कि उसने पहली बार में उस पर निर्णय क्यों लिया।
- enable_hashagg, enable_material: ये सुविधाएं PostgreSQL के लिए अपेक्षाकृत नई हैं। हैश एग्रीगेशन का आक्रामक रूप से उपयोग करना संस्करण 8.4 में पेश किया गया था, और 9.0 में अधिक आक्रामक भौतिककरण। यदि आप अपने EXPLAIN
आउटपुट में उन प्रकार के नोड्स देख रहे हैं और वे कुछ गलत कर रहे हैं, क्योंकि यह कोड इतना नया है कि इसमें कुछ पुरानी सुविधाओं की तुलना में एक सीमा या बग होने की संभावना थोड़ी अधिक है। यदि आपके पास पोस्टग्रेएसक्यूएल के पुराने संस्करणों में ठीक काम करने वाली योजना थी, लेकिन इनमें से किसी एक नोड प्रकार का उपयोग करता है और परिणामस्वरूप बहुत खराब प्रदर्शन करता है, तो इन सुविधाओं को अक्षम करने से कभी-कभी आप पहले के व्यवहार में वापस आ सकते हैं-साथ ही साथ कुछ प्रकाश भी चमक सकते हैं क्यों अनुकूलक ने उपयोगी प्रतिक्रिया के रूप में गलत काम किया। ध्यान दें कि यह आमतौर पर PostgreSQL में अधिक उन्नत सुविधाओं को पेश करने का तरीका है: समस्या निवारण उद्देश्यों के लिए इसे बंद करने के विकल्प के साथ, यदि पहले के संस्करणों ने चीजों को कैसे निष्पादित किया था, इसके सापेक्ष कोई योजना प्रतिगमन साबित होता है। - cursor_tuple_fraction: यदि आप किसी क्वेरी से सभी पंक्तियों को वापस पढ़ने का इरादा नहीं रखते हैं, तो आपको इसे लागू करने के लिए एक कर्सर का उपयोग करना चाहिए। उस स्थिति में, ऑप्टिमाइज़र प्राथमिकता देने की कोशिश करता है कि क्या यह आपको पहली पंक्ति जल्दी वापस देता है, या क्या वह इस पैरामीटर के आधार पर पूरी क्वेरी को ऑप्टिमाइज़ करना पसंद करता है। डिफ़ॉल्ट रूप से डेटाबेस मानता है कि जब आप कर्सर का उपयोग करते हैं तो आप 10% क्वेरी को फिर से पढ़ रहे होंगे। इस पैरामीटर को समायोजित करने से आप यह अपेक्षा कर सकते हैं कि आप इससे कम या अधिक पढ़ेंगे।
इन सभी मापदंडों और क्वेरी ट्वीक को ट्राइएज समायोजन पर विचार किया जाना चाहिए। आप इनके साथ हमेशा के लिए नहीं चलना चाहते (शायद join_collapse_limit को छोड़कर)। आप जाम से बाहर निकलने के लिए उनका उपयोग करते हैं, और फिर उम्मीद है कि आप यह पता लगा लेंगे कि खराब योजना का वास्तविक अंतर्निहित कारण क्या है - खराब आंकड़े, अनुकूलक सीमा / बग, या कुछ और - और फिर उस दिशा से समस्या का समाधान करें। जितना अधिक आप अनुकूलक व्यवहार को एक दिशा में आगे बढ़ा रहे हैं, उतना ही अधिक आप अपने डेटा में भविष्य में होने वाले परिवर्तनों से अवगत होंगे, जिससे यह धक्का अब सही नहीं रहेगा। यदि आप उनका सही उपयोग करते हैं, तो यह अध्ययन करने के तरीके के रूप में कि आपको गलत योजना क्यों मिली (जिस दृष्टिकोण का मैंने पोस्टग्रेएसक्यूएल 9.0 उच्च प्रदर्शन के क्वेरी ऑप्टिमाइज़ेशन अध्याय में उपयोग किया था), जिस तरह से आप पोस्टग्रेएसक्यूएल में चीजों पर संकेत देते हैं, उसके परिणामस्वरूप आपको हर रन छोड़ना चाहिए- खराब अनुकूलक व्यवहार के साथ भविष्य में समस्या के उस वर्ग से बचने के तरीके के बारे में थोड़ा और समझदार