जवाबों:
बताते हुए_EXPLAIN.pdf भी मदद कर सकता है।
जो हिस्सा मैंने हमेशा भ्रमित किया वह स्टार्टअप लागत बनाम कुल लागत है। मैं इसे हर बार भूल जाता हूं, जो मुझे यहां वापस लाता है, जो मुझे अंतर नहीं समझाता, यही कारण है कि मैं यह जवाब लिख रहा हूं। यह वही है जो मैंने पोस्टग्रेज EXPLAINडॉक्यूमेंटेशन से प्राप्त किया है , जैसा कि मैं इसे समझता हूं।
यहां एक एप्लिकेशन से एक उदाहरण दिया गया है जो एक मंच का प्रबंधन करता है:
EXPLAIN SELECT * FROM post LIMIT 50;
Limit (cost=0.00..3.39 rows=50 width=422)
-> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422)
यहाँ PgAdmin से चित्रमय विवरण दिया गया है:
(जब आप PgAdmin का उपयोग कर रहे हैं, तो आप लागत विवरण को पढ़ने के लिए अपने माउस को एक घटक पर इंगित कर सकते हैं।)
लागत लागत जैसे की एक टपल के रूप में प्रस्तुत किया जाता है, LIMITहै cost=0.00..3.39और क्रमिक रूप से स्कैनिंग की लागत postहै cost=0.00..15629.12। टपल में पहला नंबर स्टार्टअप लागत और दूसरा नंबर कुल लागत है । क्योंकि मैंने उपयोग किया EXPLAINऔर नहीं EXPLAIN ANALYZE, ये लागत अनुमान हैं, वास्तविक उपाय नहीं।
एक जटिलता के रूप में, प्रत्येक "माता-पिता" नोड की लागत में उसके बच्चे के नोड्स की लागत शामिल है। पाठ प्रतिनिधित्व में, पेड़ को इंडेंटेशन द्वारा दर्शाया जाता है, उदाहरण के LIMITलिए एक माता-पिता नोड है और Seq Scanइसका बच्चा है। PgAdmin प्रतिनिधित्व में, तीर बच्चे से माता-पिता तक इंगित करता है - डेटा के प्रवाह की दिशा - जो कि यदि आप ग्राफ सिद्धांत से परिचित हैं, तो काउंटरिंटिव हो सकता है।
दस्तावेज में कहा गया है कि सभी बाल नोड्स की लागत शामिल है, लेकिन ध्यान दें कि माता-पिता 3.39की कुल लागत बच्चे की कुल लागत से बहुत कम है 15629.12। कुल लागत समावेशी नहीं है क्योंकि एक घटक की तरह LIMITइसके पूरे इनपुट को संसाधित करने की आवश्यकता नहीं है। Postgres प्रलेखनEXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; में उदाहरण देखें ।EXPLAIN
ऊपर दिए गए उदाहरण में, दोनों घटकों के लिए स्टार्टअप का समय शून्य है, क्योंकि पंक्तियों को लिखने से पहले न तो घटक को कोई प्रसंस्करण करने की आवश्यकता होती है: एक अनुक्रमिक स्कैन तालिका की पहली पंक्ति को पढ़ता है और इसे उत्सर्जित करता है। LIMITअपनी पहली पंक्ति पढ़ता है और फिर इसे उत्सर्जन करता है।
किसी भी पंक्तियों को आउटपुट करने के लिए शुरू करने से पहले एक घटक को बहुत अधिक प्रसंस्करण करने की आवश्यकता कब होगी? इसके कई संभावित कारण हैं, लेकिन आइए एक स्पष्ट उदाहरण देखें। यहां पहले से समान क्वेरी है लेकिन अब एक ORDER BYक्लॉज है:
EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;
Limit (cost=23283.24..23283.37 rows=50 width=422)
-> Sort (cost=23283.24..23859.27 rows=230412 width=422)
Sort Key: body
-> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422)
और रेखांकन:
एक बार फिर, अनुक्रमिक स्कैन पर postकोई स्टार्टअप लागत नहीं है: यह तुरंत पंक्तियों को आउटपुट करना शुरू कर देता है। लेकिन सॉर्ट में एक महत्वपूर्ण स्टार्टअप लागत होती है 23283.24क्योंकि इसे पूरी पंक्ति को छाँटना पड़ता है, इससे पहले कि यह एक पंक्ति को भी आउटपुट कर सके । सॉर्ट की कुल लागत 23859.27स्टार्टअप लागत से केवल थोड़ी अधिक है, इस तथ्य को दर्शाती है कि एक बार पूरे डेटासेट को छांटने के बाद, सॉर्ट किए गए डेटा को बहुत जल्दी से उत्सर्जित किया जा सकता है।
ध्यान दें कि स्टार्टअप का समय LIMIT 23283.24बिलकुल स्टार्टअप टाइम के बराबर होता है। यह इसलिए नहीं है क्योंकि LIMITखुद के पास एक उच्च स्टार्टअप समय है। यह वास्तव में अपने आप में शून्य स्टार्टअप समय है, लेकिन EXPLAINप्रत्येक माता-पिता के लिए बच्चे की सभी लागतों को रोल करता है, इसलिए LIMITस्टार्टअप समय में अपने बच्चों के स्टार्टअप समय शामिल हैं।
लागतों का यह रोलअप प्रत्येक व्यक्तिगत घटक की निष्पादन लागत को समझना मुश्किल बना सकता है। उदाहरण के लिए, हमारे LIMITपास शून्य स्टार्टअप समय है, लेकिन यह पहली नज़र में स्पष्ट नहीं है। इस कारण से, कई अन्य लोगों को समझाने के लिए लिंक किया गया ।.desesz.com, ह्यूबर्ट लुबाक्ज़ेव्स्की (उर्फ डिप्सज़) द्वारा बनाया गया एक उपकरण, जो EXPLAINअन्य चीजों के साथ-साथ माता-पिता की लागत से बच्चे की लागत को घटाकर समझने में मदद करता है । उन्होंने अपने टूल के बारे में एक संक्षिप्त ब्लॉग पोस्ट में कुछ अन्य जटिलताओं का उल्लेख किया है।
यह सबसे अधिक इंडेंटेड कम से कम इंडेंटेड से निष्पादित होता है, और मुझे विश्वास है कि योजना के नीचे से ऊपर तक। (इसलिए यदि दो इंडेंट किए गए सेक्शन हैं, तो पेज के नीचे वाला सबसे पहले निष्पादित होता है, फिर जब वे दूसरे निष्पादन को पूरा करते हैं, तो उनके साथ जुड़ने वाला नियम निष्पादित होता है।)
विचार यह है कि प्रत्येक चरण में 1 या 2 डेटासेट होते हैं जो किसी नियम से आते हैं और संसाधित होते हैं। यदि सिर्फ एक डेटासेट, उस ऑपरेशन को उस डेटा सेट पर किया जाता है। (उदाहरण के लिए, किसी अनुक्रमणिका को स्कैन करने के लिए कि आप क्या पंक्तियाँ चाहते हैं, डेटासेट फ़िल्टर करें या उसे सॉर्ट करें।) यदि दो, दो डेटासेट दो चीज़ें हैं जो आगे इंडेंट हैं, और वे आपके द्वारा देखे गए नियम से जुड़ जाते हैं। अधिकांश नियमों का अर्थ यथोचित रूप से आसानी से अनुमान लगाया जा सकता है (विशेषकर यदि आपने पहले स्पष्टीकरण योजनाओं का एक गुच्छा पढ़ा है), हालांकि आप केवल वाक्यांश को फेंककर प्रलेखन या (आसान) में देखकर व्यक्तिगत वस्तुओं को सत्यापित करने का प्रयास कर सकते हैं। Google जैसे कुछ कीवर्डEXPLAIN ।
यह स्पष्ट रूप से एक पूर्ण स्पष्टीकरण नहीं है, लेकिन यह पर्याप्त संदर्भ प्रदान करता है कि आप आमतौर पर जो चाहें कर सकते हैं। उदाहरण के लिए एक वास्तविक डेटाबेस से इस योजना पर विचार करें:
explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';
------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge Join (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
Merge Cond: (a.orderid = b.orderid)
-> Sort (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
Sort Key: a.orderid
Sort Method: quicksort Memory: 1695kB
-> Bitmap Heap Scan on orderitemattribute a (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
Recheck Cond: ((attributeid)::text = 'display-album'::text)
-> Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
Index Cond: ((attributeid)::text = 'display-album'::text)
-> Sort (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
Sort Key: b.orderid
Sort Method: quicksort Memory: 76kB
-> Bitmap Heap Scan on orderitem b (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
Recheck Cond: ((productid)::text = 'ModernBook'::text)
-> Bitmap Index Scan on id_orderitem_productid (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
Index Cond: ((productid)::text = 'ModernBook'::text)
Total runtime: 842.134 ms
(17 rows)
इसे अपने लिए पढ़ने की कोशिश करें और देखें कि क्या यह समझ में आता है।
मैंने जो पढ़ा है वह यह है कि डेटाबेस सबसे पहले id_orderitem_productidइंडेक्स को स्कैन करता है , इसका उपयोग करके वह पंक्तियों को orderitemढूंढता है जिनसे वह चाहता है , फिर सॉर्टसेट का उपयोग कर डेटा सॉर्ट (रैम में फिट नहीं होने पर सॉर्ट बदल जाएगा)।
इसके बाद, यह orditematt_attributeid_idxउन पंक्तियों को खोजने के लिए स्कैन करता है orderitemattributeजिनसे यह चाहता है और फिर उस डेटासेट को क्विकॉर्ट का उपयोग करके सॉर्ट करता है।
यह तब दो डेटासेट लेता है और उन्हें मर्ज करता है। (एक मर्ज जॉइन "ज़िपिंग" ऑपरेशन का एक प्रकार है जहां यह समानांतर में दो सॉर्ट किए गए डेटासेट को चलता है, जब वे मेल खाते हैं, तो पंक्ति को छोड़ते हुए।
जैसा कि मैंने कहा, आप आंतरिक भाग से लेकर बाहरी भाग, नीचे से ऊपर तक की योजना के माध्यम से काम करते हैं।
एक ऑनलाइन सहायक उपकरण भी उपलब्ध है, डीपेज़ , जो उजागर करेगा कि विश्लेषण परिणामों के महंगे हिस्से कहां हैं।
यह भी एक है, यहाँ एक ही परिणाम है , जो मुझे यह स्पष्ट कर देता है कि समस्या कहां है।
PgAdmin आपको व्याख्या योजना का चित्रमय प्रतिनिधित्व दिखाएगा। दोनों के बीच आगे और पीछे स्विच करने से वास्तव में आपको यह समझने में मदद मिल सकती है कि टेक्स्ट प्रतिनिधित्व का क्या मतलब है। हालाँकि, यदि आप जानना चाहते हैं कि यह क्या हो रहा है, तो आप हमेशा GUI का उपयोग करने में सक्षम हो सकते हैं।
PostgreSQL का आधिकारिक दस्तावेज विवरण के आउटपुट को समझने के तरीके पर एक दिलचस्प, गहन विवरण प्रदान करता है।