2017-05-05 15 views
5
के लिए

निम्नलिखित एसक्यूएल क्वेरी पर विचार करें अंदर कार्यों प्रदर्शन:स्मार्ट तर्क प्रश्नों PostgreSQL

SELECT a,b,c 
FROM t 
WHERE (id1 = :p_id1 OR :p_id1 IS NULL) AND (id2 = :p_id2 OR :p_id2 IS NULL) 

Markus Winand अपनी पुस्तक में सभी का सबसे बुरा प्रदर्शन विरोधी पैटर्न में से एक के रूप में इस दृष्टिकोण "SQL Performance explained" नाम, और बताते हैं क्यों (डेटाबेस को सबसे खराब मामले के लिए योजना तैयार करना है जब सभी फ़िल्टर अक्षम हैं)।

लेकिन बाद में वह यह भी लिखते हैं कि पोस्टग्रेएसक्यूएल के लिए यह समस्या केवल तब होती है जब एक कथन (PreparedStatement) को फिर से उपयोग करते समय संभाल लें।

भी मान लें कि अब क्वेरी ऊपर समारोह में लपेटा जाता है, की तरह कुछ:

  1. इस समस्या को अभी भी होने की स्थिति में होते हैं होगा:

    CREATE FUNCTION func(IN p_id1 BIGINT,IN p_id2 BIGINT) 
    ... 
    $BODY$ 
        BEGIN 
        ... 
        END; 
    $BODY$ 
    

    अब तक मैं कुछ बिंदुओं की गलतफहमी है फ़ंक्शन रैपिंग? (मैंने फ़ंक्शन कॉल के लिए निष्पादन योजना देखने की कोशिश की है, लेकिन पोस्टग्रेस मुझे SET auto_explain.log_nested_statements = ON के साथ भी आंतरिक फ़ंक्शन कॉल के विवरण नहीं दिखाता है)।

  2. मान लें कि मैं विरासत परियोजना के साथ काम कर रहा हूं और फ़ंक्शन स्वयं ही नहीं बदल सकता, केवल जावा निष्पादन कोड। क्या यहां तैयार कथन से बचने और हर बार गतिशील क्वेरी का उपयोग करना बेहतर होगा? (यह मानते हुए कि निष्पादन का समय काफी सेकंड तक, काफी लंबा है)। यह कहते हैं, शायद, बदसूरत दृष्टिकोण:


getSession().doWork(connection -> { 
    ResultSet rs = connection.createStatement().executeQuery("select * from func("+id1+","+id2+")"); 
    ... 
}) 

उत्तर

2

1. यह निर्भर करता है।

तैयार कथन का उपयोग नहीं करते समय, PostgreSQL पैरामीटर मानों का उपयोग करके हर बार एक क्वेरी की योजना बनाते हैं। इसे कस्टम प्लान के रूप में जाना जाता है।

तैयार बयान के साथ

(और तुम सही हो, PL/pgSQL कार्यों तैयार बयान का उपयोग करते हैं) यह और अधिक जटिल है। PostgreSQL कथन तैयार करता है (इसके पाठ को पार्स करता है और पार्स पेड़ स्टोर करता है), लेकिन इसे हर बार निष्पादित करने पर फिर से योजना बनाते हैं। कस्टम योजना कम से कम 5 बार उत्पन्न होती है। कि योजनाकार का उपयोग कर विचार करता है के बाद एक सामान्य योजना (i। ई। पैरामीटर-मान-स्वतंत्र) अगर यह लागत अब तक बने हुए कस्टम योजनाओं की औसत लागत की तुलना में कम है।

ध्यान दें, एक योजना की है कि लागत योजनाकार का एक अनुमान है, न कि वास्तविक आई/ओ संचालन या CPU चक्र है।

तो, समस्या हो सकती है, लेकिन इसके लिए आपको कुछ दुर्भाग्य की आवश्यकता है।

2. दृष्टिकोण क्योंकि यह समारोह के व्यवहार में परिवर्तन नहीं करता आप, सुझाव काम नहीं करेगा।

सामान्य रूप से यह PostgreSQL के लिए पैरामीटर का उपयोग न करने के लिए इतना बदसूरत नहीं है (क्योंकि यह ई जी ओरेकल के लिए है), क्योंकि PostgreSQL ने योजनाओं के लिए साझा कैश नहीं किया है। तैयार योजना प्रत्येक बैकएंड की स्मृति में जमा हो जाती है, तो फिर से योजना बना अन्य सत्र को प्रभावित नहीं करेगा।

लेकिन जहां तक ​​मुझे पता है, वर्तमान में योजनाकारों को कस्टम योजनाओं का उपयोग करने के लिए मजबूर करने का कोई तरीका नहीं है (5 निष्पादन के बाद पुनः कनेक्ट करने के अलावा ...)।

+0

आपके उत्तर के लिए धन्यवाद। 1 बिंदु के बारे में मुझे काफी समझ में नहीं आता है। क्या इसका मतलब यह है कि वर्णित समस्या आमतौर पर PostgreSQL के लिए कोई समस्या नहीं है जब इस प्रकार के प्रश्न फ़ंक्शन में लपेटे जाते हैं? – Andremoniy

+0

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

+0

ठीक है, लेकिन मुझे लगता है कि हमें हमेशा सबसे खराब मामले पर विचार करना चाहिए, है ना? ऐसा लगता है कि सबसे बुरी स्थिति में यह अभी भी समस्या होगी। और क्या मैं सही ढंग से समझता हूं कि एक समारोह के लिए तैयार कथन का उपयोग किए बिना योजना की गणना की जाएगी? – Andremoniy