आपके परीक्षण कोड का निम्नलिखित विस्तार सूचनात्मक है:
CREATE OR REPLACE FUNCTION test_multi_calls1(one integer)
RETURNS integer
AS $BODY$
BEGIN
RAISE NOTICE 'Immutable called with %', one;
RETURN one;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
CREATE OR REPLACE FUNCTION test_multi_calls2(one integer)
RETURNS integer
AS $BODY$
BEGIN
RAISE NOTICE 'Volatile called with %', one;
RETURN one;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;
WITH data AS
(
SELECT 10 AS num
UNION ALL SELECT 10
UNION ALL SELECT 20
)
SELECT test_multi_calls1(num)
FROM data
where test_multi_calls2(40) = 40
and test_multi_calls1(30) = 30
आउटपुट:
NOTICE: Immutable called with 30
NOTICE: Volatile called with 40
NOTICE: Immutable called with 10
NOTICE: Volatile called with 40
NOTICE: Immutable called with 10
NOTICE: Volatile called with 40
NOTICE: Immutable called with 20
यहां हम देख सकते हैं कि चयन-सूची में अपरिवर्तनीय फ़ंक्शन को कई बार कहा जाता था, जहां क्लॉज में इसे एक बार कहा जाता था, जबकि अस्थिर को तीन बार कहा जाता था।
महत्वपूर्ण बात यह नहीं है कि PostgreSQL केवल STABLE
. को कॉल करेगा या IMMUTABLE
एक ही डेटा के साथ एक बार कार्य करें - आपका उदाहरण स्पष्ट रूप से दिखाता है कि यह मामला नहीं है - यह है कि यह हो सकता है इसे केवल एक बार कॉल करें। या शायद यह इसे दो बार कॉल करेगा जब इसे एक अस्थिर संस्करण को 50 बार कॉल करना होगा, और इसी तरह।
विभिन्न लागतों और लाभों के साथ, विभिन्न तरीकों से स्थिरता और अपरिवर्तनीयता का लाभ उठाया जा सकता है। आप जिस प्रकार की बचत का सुझाव दे रहे हैं, उसे प्रदान करने के लिए इसे चुनिंदा-सूचियों के साथ बनाना चाहिए, इसे परिणामों को कैश करना होगा, और फिर कैश किए गए परिणाम को वापस करने या कैश पर फ़ंक्शन को कॉल करने से पहले इस कैश में प्रत्येक तर्क (या तर्कों की सूची) को देखना होगा। -कुमारी। यह आपके फ़ंक्शन को कॉल करने की तुलना में अधिक महंगा होगा, यहां तक कि उस स्थिति में भी जहां कैश-हिट का उच्च प्रतिशत था (0% कैश हिट हो सकता है जिसका अर्थ है कि इस "ऑप्टिमाइज़ेशन" ने बिना किसी लाभ के अतिरिक्त काम किया)। यह शायद केवल अंतिम पैरामीटर और परिणाम को संग्रहीत कर सकता है, लेकिन फिर से यह पूरी तरह से बेकार हो सकता है।
यह विशेष रूप से इसलिए है क्योंकि स्थिर और अपरिवर्तनीय कार्य अक्सर सबसे हल्के कार्य होते हैं।
हालांकि जहां क्लॉज के साथ, test_multi_calls1
. की अपरिवर्तनीयता PostgreSQL को वास्तव में दिए गए SQL के सादे अर्थ से क्वेरी को पुनर्गठित करने की अनुमति देता है:
पूरी तरह से एक अलग क्वेरी योजना के लिए:
यह एक प्रकार का उपयोग है जो PostgreSQL स्थिर और अपरिवर्तनीय बनाता है - परिणामों की कैशिंग नहीं, बल्कि विभिन्न प्रश्नों में प्रश्नों का पुनर्लेखन जो अधिक कुशल हैं लेकिन समान परिणाम देते हैं।
यह भी ध्यान दें कि test_multi_calls1(30) को test_multi_calls2(40) से पहले कॉल किया जाता है, चाहे वे किस क्रम में क्लॉज में दिखाई दें। इसका मतलब यह है कि यदि पहली कॉल के परिणामस्वरूप कोई पंक्तियाँ वापस नहीं आती हैं (= 30
. को बदलें = 31
. के साथ परीक्षण करने के लिए) तो अस्थिर फ़ंक्शन को बिल्कुल भी नहीं कहा जाएगा - फिर चाहे जो and
के किस तरफ है ।
यह विशेष प्रकार का पुनर्लेखन अपरिवर्तनीयता या स्थिरता पर निर्भर करता है। साथ में where test_multi_calls1(30) != num
क्वेरी री-राइटिंग अपरिवर्तनीय के लिए होगी, लेकिन केवल स्थिर कार्यों के लिए नहीं। where test_multi_calls1(num) != 30
. के साथ यह बिल्कुल नहीं होगा (एकाधिक कॉल) हालांकि अन्य अनुकूलन संभव हैं:
इंडेक्स स्कैन के साथ केवल स्थिर और अपरिवर्तनीय कार्यों वाले एक्सप्रेशन का उपयोग किया जा सकता है। VOLATILE फ़ंक्शंस वाले एक्सप्रेशन नहीं कर सकते। कॉलों की संख्या कम हो सकती है या नहीं भी हो सकती है, लेकिन इससे भी महत्वपूर्ण बात यह है कि कॉल के परिणाम शेष क्वेरी में अधिक कुशल तरीके से उपयोग किए जाएंगे (केवल बड़ी टेबल पर वास्तव में मायने रखता है, लेकिन फिर यह बड़े पैमाने पर बना सकता है अंतर)।
कुल मिलाकर, संस्मरण के संदर्भ में अस्थिरता श्रेणियों के बारे में न सोचें, बल्कि PostgreSQL के क्वेरी प्लानर को संपूर्ण प्रश्नों को तार्किक रूप से समान (समान परिणाम) लेकिन अधिक कुशल तरीके से पुनर्गठित करने के अवसर देने के संदर्भ में।