2013-02-18 49 views
5

अगर मैं निम्नलिखित खिलौना क्वेरीक्या पोस्टग्रेस्क्ल plpgsql/sql समर्थन खंड में लघु सर्किट का समर्थन करता है?

SELECT * 
FROM my_tables 
WHERE my_id in (
    SELECT my_other_id 
    FROM my_other_tables 
) AND some_slow_func(arg) BETWEEN 1 AND 2; 

चाहेंगे कहां खंड शॉर्ट सर्किट में पहली शर्त दूसरी शर्त जो एक जटिल रन समय होता?

मैं कुछ एसक्यूएल वास्तव में plpgsql में एक के लिए लूप का हिस्सा है उस पर काम कर रहा हूँ, और मैं some_slow_func साथ के लिए लूप के दायरे के भीतर सभी रिकॉर्ड से अधिक पुनरावृत्तियों कि my_other_tables में मौजूद हैं, और फिर परीक्षण कर सकता है ()। लेकिन अगर मैं एसक्यूएल का समर्थन करता हूं तो मुझे उत्सुकता है, या plpgsql लघु सर्किटिंग का समर्थन करता है।

कुछ अनुसंधान: मैं Postgres मेलिंग सूची में देखा और पाया सामान्य रूप में यह कह एसक्यूएल लघु सर्किटिंग का समर्थन नहीं करता:

http://www.postgresql.org/message-id/[email protected]om

लेकिन प्रतिक्रियाओं में से एक का कहना है कि आदेश के माध्यम से लागू किया जा सकता है subselects। मुझे बिल्कुल यकीन नहीं है कि वह किस बारे में बात कर रहा है। मुझे पता है कि उप-चयन क्या है, लेकिन मुझे यकीन नहीं है कि आदेश कैसे लागू किया जाएगा? क्या कोई मेरे लिए यह स्पष्ट कर सकता है?

+0

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

उत्तर

6

दस्तावेज के रूप में, WHERE खंड में मूल्यांकन आदेश अप्रत्याशित माना जाना चाहिए।

यह सबक्वायरीज़ के साथ अलग है। वर्तमान संस्करणों के साथ, मूल्यांकन आदेश को चलाने के लिए सबसे सरल और सामान्य तकनीक एक सीटीई में एक सबक्वायरी लिखना है। सुनिश्चित करें कि IN(...) पहले मूल्यांकन किया जाता है बनाने के लिए, अपने कोड के रूप में लिखा जा सकता है: और है कि आप tweak कर सकते हैं

WITH subquery AS 
(select * from my_tables 
    WHERE my_id in (SELECT my_other_id FROM my_other_tables) 
) 
SELECT * FROM subquery 
    WHERE some_slow_func(arg) BETWEEN 1 AND 2; 

कुछ अपने कार्य की लागत अनुकूलक कि यह धीमी है करने के लिए संकेत करने के लिए है। एक समारोह के लिए डिफ़ॉल्ट लागत 100 है, और यह की तरह एक बयान के साथ बदला जा सकता है:

ALTER FUNCTION funcname(argument types) cost N; 

जहां N अनुमानित प्रति कॉल लागत है, एक मनमाना इकाई है कि Planner Cost Constants की तुलना में किया जाना चाहिए में व्यक्त किया।

+0

हां, सेट का उपयोग सेट को सीमित करने के लिए एक अच्छा त्वरित तरीका होगा। यकीन नहीं है कि मैंने इस बारे में क्यों नहीं सोचा .... मुझे साथ उपयोग करना अच्छा लगता है। इसके अलावा, योजनाकार की लागत को बदलने के बारे में भी नहीं सोचा था। मैं इसके बारे में जानता था लेकिन मैंने हमेशा पोस्टग्रेज़ को ऑप्टिमाइज़ेशन की देखभाल करने दिया है। मैंने वास्तव में पहले कभी इसका उपयोग नहीं किया है, लेकिन इसमें और अधिक पढ़ा जाएगा। इसे मेरे ध्यान में लाने के लिए धन्यवाद! – enigmasck

+0

जब आप फ़ंक्शन को परिभाषित करते हैं तो आप 'लागत एन' भी शामिल कर सकते हैं। – jpmc26

0

the Postgresql docs और this answer by Tom Lane के अनुसार, WHERE बाधाओं के निष्पादन का आदेश विश्वसनीय नहीं है।

मुझे लगता है कि यहां आपकी सबसे अच्छी शर्त आपके फ़ंक्शन के शीर्ष में आपके WHERE क्लॉज के उस अन्य भाग को जोड़ने और "तेज़ी से विफल" हो सकती है; यानी, अपने कार्य में my_id in ( SELECT my_other_id FROM my_other_tables) चलाएं, और यदि यह पास नहीं होता है, तो आप गहन प्रसंस्करण करने से पहले वहां वापस आएं। यह आपको एक ही प्रभाव के बारे में मिलना चाहिए।

+0

संदर्भों के लिए धन्यवाद। मैं पूरे दिन postgresql दस्तावेज देख रहा हूं, और मैं उस स्पष्टीकरण में नहीं आया था। मैं आपकी त्वरित प्रतिक्रिया की सराहना करता हूं। – enigmasck

+0

कोई समस्या नहीं है। एक टिप - जब आप उन मंचों को देख रहे हैं, तो नीचे आमतौर पर "प्रतिक्रिया में" और "प्रतिक्रियाएं" के लिए अनुभाग होते हैं। यदि आप प्रतिक्रियाओं के तहत लिंक का पालन करते हैं, तो आपको शायद अधिक जानकारी मिल जाएगी। इस मामले में, मैंने जो कुछ किया वह ओपी में आपके द्वारा लिंक किए गए पोस्ट पर टॉम लेन द्वारा प्रतिक्रिया का पालन किया गया था। –

2

मुझे पता है कि यह एक पुराना सवाल है, लेकिन हाल ही में इसी तरह की समस्या में भाग गया, और WHERE खंड में एक केस पूर्वानुमान का उपयोग करके पाया गया कि मेरे लिए बेहतर काम किया। उपरोक्त उत्तर के संदर्भ में:

SELECT * 
    FROM my_tables 
WHERE CASE WHEN my_id in (SELECT my_other_id 
          FROM my_other_tables) 
      AND some_slow_func(arg) BETWEEN 1 AND 2 
      THEN 1 
      ELSE 0 
     END = 1; 

यह एसक्यूएल के लिए बनाता है जो थोड़ा अधिक डीबी अज्ञेयवादी है। बेशक, अगर आपके पास my_id पर कुछ है, तो यह इंडेक्स का उपयोग नहीं कर सकता है, लेकिन आपके द्वारा संदर्भित संदर्भ के आधार पर, यह एक अच्छा विकल्प हो सकता है।