@ Alci के उत्तर पर विस्तृत करने के लिए:
PostgreSQL परवाह नहीं करता है कि आप किस क्रम में चीजें लिखते हैं
PostgreSQL WHERE
क्लाज में प्रविष्टियों के क्रम के बारे में बिल्कुल भी परवाह नहीं करता है , और लागत और अकेले चयन के आधार पर अनुक्रमित और निष्पादन आदेश चुनता है।
जिस क्रम में ज्वाइनिंग लिखी जाती है उसे भी कॉन्फ़िगर किए जाने तक अनदेखा किया जाता है join_collapse_limit
; अगर वहाँ से अधिक जोड़ रहे हैं, यह उन्हें आदेश में लिखा है कि वे निष्पादित करेंगे।
सबक्वेरी को उस क्वेरी से पहले या बाद में निष्पादित किया जा सकता है, जिसमें सबसे तेज़, इतनी देर तक सबकुछ निर्भर करता है, क्योंकि बाहरी क्वेरी वास्तव में जानकारी की आवश्यकता से पहले सबक्वेरी निष्पादित होती है। अक्सर वास्तविकता में उपसमुच्चय को बीच में ही निष्पादित किया जाता है, या बाहरी क्वेरी के साथ इंटरलेय किया जाता है।
कोई गारंटी नहीं है कि PostgreSQL वास्तव में क्वेरी के कुछ हिस्सों को निष्पादित करेगा। उन्हें पूरी तरह से अनुकूलित किया जा सकता है। यह महत्वपूर्ण है यदि आप साइड-इफेक्ट्स वाले कार्यों को कहते हैं।
PostgreSQL आपकी क्वेरी को बदल देगा
PostgreSQL परिणामों को परिवर्तित नहीं करते हुए उन्हें तेज गति से चलाने के लिए सटीक समान प्रभावों को बनाए रखते हुए पोस्टग्रेज को भारी रूप से परिवर्तित कर देगा।
एक उपमहाद्वीप के बाहर की शर्तों को उपश्रेणी में नीचे धकेला जा सकता है , इसलिए वे उप-भाग के भाग के रूप में निष्पादित होते हैं न कि जहां आपने उन्हें बाहरी प्रश्न में लिखा था
उपनगर की शर्तें बाहरी क्वेरी तक खींची जा सकती हैं, इसलिए उनका निष्पादन बाहरी क्वेरी के हिस्से के रूप में किया जाता है, न कि आपने उन्हें उप-केंद्र में लिखा था
उपमहाद्वीप, और अक्सर, बाहरी तालिका में शामिल होने के लिए चपटा होता है । जैसा है वैसा ही सच है EXISTS
औरNOT EXISTS
जिज्ञासाएं होती ।
दृश्य दृश्य का उपयोग करने वाली क्वेरी में चपटा हो जाता है
SQL फ़ंक्शन अक्सर कॉलिंग क्वेरी में इनबिल्ड हो जाते हैं
... और प्रश्नों के लिए कई अन्य परिवर्तन किए गए हैं, जैसे निरंतर अभिव्यक्ति पूर्व मूल्यांकन, कुछ उपश्रेणियों का डी-सहसंबंध, और अन्य योजनाकार / अनुकूलक चाल के सभी प्रकार।
सामान्य तौर पर PostgreSQL बड़े पैमाने पर आपकी क्वेरी को बदल सकता है और फिर से लिख सकता है, इस बिंदु पर जहाँ इनमें से प्रत्येक प्रश्न:
select my_table.*
from my_table
left join other_table on (my_table.id = other_table.my_table_id)
where other_table.id is null;
select *
from my_table
where not exists (
select 1
from other_table
where other_table.my_table_id = my_table.id
);
select *
from my_table
where my_table.id not in (
select my_table_id
from other_table
where my_table_id is not null
);
आमतौर पर सभी बिल्कुल एक ही क्वेरी योजना का उत्पादन करेंगे। (यह मानते हुए कि मैंने उपरोक्त किसी भी तरह की गूंगी गलतियों को नहीं किया है)।
केवल क्वेरी को ऑप्टिमाइज़ करने का प्रयास करना असामान्य नहीं है, यह जानने के लिए कि क्वेरी प्लानर पहले से ही आपके द्वारा आजमाए गए ट्रिक्स का पता लगा चुका है और उन्हें अपने आप ही लागू कर देता है, इसलिए हाथ से अनुकूलित संस्करण मूल से बेहतर नहीं है।
सीमाएं
प्लानर / ऑप्टिमाइज़र सर्वव्यापी से बहुत दूर है, और यह पूरी तरह से निश्चित होने की आवश्यकता से सीमित है यह क्वेरी के प्रभाव, निर्णय लेने के लिए उपलब्ध डेटा, लागू किए गए नियमों और सीपीयू समय को बदल नहीं सकता है। यह अनुकूलन को पूरा करने में खर्च कर सकता है। उदाहरण के लिए:
प्लानर द्वारा रखे गए आँकड़ों पर निर्भर करता है ANALYZE
(आमतौर पर ऑटोवैक्युम के माध्यम से)। यदि ये पुराने हैं, तो योजना का विकल्प खराब हो सकता है।
आंकड़े केवल एक नमूना हैं, इसलिए वे नमूने के प्रभाव के कारण भ्रामक हो सकते हैं, खासकर यदि बहुत छोटा नमूना लिया जाता है। खराब योजना विकल्पों का परिणाम हो सकता है।
आंकड़े तालिका के बारे में कुछ प्रकार के डेटा का ट्रैक नहीं रखते हैं, जैसे स्तंभों के बीच संबंध। यह खराब निर्णय लेने के लिए योजनाकार का नेतृत्व कर सकता है जब यह मानता है कि चीजें स्वतंत्र हैं जब वे नहीं हैं।
प्लानर लागत मापदंडों पर निर्भर करता है, जैसे random_page_cost
कि यह उस विशेष सिस्टम पर विभिन्न ऑपरेशनों की सापेक्ष गति बताता है, जिस पर यह स्थापित है। ये केवल मार्गदर्शक हैं। यदि वे बुरी तरह से गलत हैं तो वे खराब योजना विकल्पों को जन्म दे सकते हैं।
LIMIT
या के साथ किसी भी उपश्रेणी को OFFSET
चपटा नहीं किया जा सकता है या पुलअप / पुशडाउन के अधीन नहीं किया जा सकता है। इसका मतलब यह नहीं है कि यह बाहरी क्वेरी के सभी भागों से पहले निष्पादित होगा, हालांकि, या यहां तक कि यह बिल्कुल भी निष्पादित करेगा ।
सीटीई की शर्तें (एक WITH
प्रश्न में खंड ) हमेशा अपनी संपूर्णता में निष्पादित होती हैं, अगर वे बिल्कुल निष्पादित होती हैं। उन्हें चपटा नहीं किया जा सकता है, और शर्तों को सीटीई अवधि की बाधा के पार नहीं धकेला जा सकता है या नीचे नहीं खींचा जा सकता है। CTE की शर्तों को हमेशा अंतिम क्वेरी से पहले निष्पादित किया जाता है। यह गैर SQL मानक है व्यवहार है, लेकिन यह दस्तावेज के रूप में है कि पोस्टग्रेक्यूएल चीजों को कैसे करता है।
PostgreSQL में विदेशी तालिकाओं, security_barrier
विचारों और कुछ अन्य विशेष प्रकार के संबंधों पर प्रश्नों को अनुकूलित करने की एक सीमित क्षमता है
PostgreSQL सादे SQL को छोड़कर किसी भी चीज़ में लिखे फ़ंक्शन को इनलाइन नहीं करेगा, और न ही इसके और बाहरी क्वेरी के बीच पुलअप / पुशडाउन।
योजनाकार / अनुकूलक वास्तव में अभिव्यक्ति सूचकांक का चयन करने के बारे में गूंगा है, और सूचकांक और अभिव्यक्ति के बीच तुच्छ डेटा प्रकार के अंतर के बारे में।
टन अधिक, भी।
तुम्हारे सवाल
आपकी क्वेरी के मामले में:
select 1
from workdays day
where day.date_day >= '2014-10-01'
and day.date_day <= '2015-09-30'
and day.offer_id in (
select offer.offer_day
from offer
inner join province on offer.id_province = province.id_province
inner join center cr on cr.id_cr = province.id_cr
where upper(offer.code_status) <> 'A'
and province.id_region in ('10' ,'15' ,'21' ,'26' ,'31' , ...,'557')
and province.id_cr in ('9' ,'14' ,'20' ,'25' ,'30' ,'35' ,'37')
)
कुछ भी नहीं एक अतिरिक्त सेट के साथ एक सरल क्वेरी में चपटा होने से रोकता है, और यह बहुत संभावना होगी।
यह संभवत: कुछ ऐसा करेगा (अप्रकाशित, स्पष्ट रूप से):
select 1
from workdays day
inner join offer on day.offer_id = offer.offer_day
inner join province on offer.id_province = province.id_province
inner join center cr on cr.id_cr = province.id_cr
where upper(offer.code_status) <> 'A'
and province.id_region in ('10' ,'15' ,'21' ,'26' ,'31' , ...,'557')
and province.id_cr in ('9' ,'14' ,'20' ,'25' ,'30' ,'35' ,'37')
and day.date_day >= '2014-10-01'
and day.date_day <= '2015-09-30';
PostgreSQL तब ज्वाइन ऑर्डर को ऑप्टिमाइज़ करेगा और अपनी सेलेक्टिविटी और रो काउंट अनुमान और उपलब्ध इंडेक्स के आधार पर तरीकों में शामिल होगा। यदि ये वास्तविक रूप से वास्तविकता को दर्शाते हैं तो यह जुड़ता है और जहाँ भी क्रम सबसे अच्छा होता है वहाँ क्लॉज एंट्रीज़ चलाता है - अक्सर उन्हें एक साथ मिलाता है, इसलिए यह इस पर थोड़ा सा काम करता है, फिर पहले भाग में वापस आता है। , आदि।
कैसे देखें कि ऑप्टिमाइज़र ने क्या किया
आप उस SQL को नहीं देख सकते हैं जो PostgreSQL आपकी क्वेरी का अनुकूलन करता है, क्योंकि यह SQL को आंतरिक क्वेरी ट्री प्रतिनिधित्व में परिवर्तित करता है और फिर उसे संशोधित करता है। आप कर सकते हैं क्वेरी योजना डंप और इसकी तुलना अन्य प्रश्नों से कर सकते हैं।
उस क्वेरी योजना या आंतरिक योजना ट्री को SQL में वापस लाने का कोई तरीका नहीं है।
http://explain.depesz.com/ में एक अच्छा क्वेरी प्लान हेल्पर है। यदि आप क्वेरी योजनाओं आदि के लिए पूरी तरह से नए हैं (जिस स्थिति में मैं अचंभित हूं तो आपने इसे इस पोस्ट के माध्यम से दूर कर दिया है) तो PgAdmin में एक ग्राफिकल क्वेरी प्लान व्यूअर है जो बहुत कम जानकारी प्रदान करता है लेकिन सरल है।
संबंधित पढ़ना:
पुशडाउन / पुलअप और चपटा करने की क्षमताओं में सुधार जारी है । PostgreSQL आमतौर पर पुल-अप / पुश-डाउन / सपाट निर्णय लेने के बारे में सही है, लेकिन हमेशा नहीं, इसलिए कभी-कभी आपको (ab) CTE या OFFSET 0
हैक का उपयोग करना पड़ता है । यदि आपको ऐसा कोई मामला मिलता है, तो क्वेरी प्लानर बग की रिपोर्ट करें।
यदि आप वास्तव में हैं, तो वास्तव में उत्सुक हैं आप debug_print_plans
कच्चे क्वेरी प्लान को देखने के लिए विकल्प का उपयोग कर सकते हैं , लेकिन मैं वादा करता हूं कि आप इसे पढ़ना नहीं चाहते हैं। वास्तव में।