अन्य उत्तर सिंटैक्स मतभेदों को अच्छी तरह से कवर करते हैं इसलिए मैं इसमें नहीं जाऊंगा। इसके बजाय यह उत्तर ओरेकल में प्रदर्शन को कवर करेगा।
Oracle ऑप्टिमाइज़र CTE के परिणामों को आंतरिक अस्थायी तालिका में सूचीबद्ध करने का विकल्प चुन सकता है। यह लागत-आधारित अनुकूलन के बजाय ऐसा करने के लिए एक अनुमानी का उपयोग करता है। ह्यूरिस्टिक कुछ ऐसा है जैसे "सीटीई को स्थिर करें यदि यह एक तुच्छ अभिव्यक्ति नहीं है और सीटीई को क्वेरी में एक से अधिक बार संदर्भित किया जाता है"। कुछ प्रश्न हैं जिनके लिए सामग्रीकरण प्रदर्शन में सुधार करेगा। कुछ प्रश्न हैं जिनके लिए सामग्रीकरण नाटकीय रूप से प्रदर्शन को नीचा दिखाएगा। निम्नलिखित उदाहरण थोड़ा सा वंचित है, लेकिन यह बिंदु को अच्छी तरह दिखाता है:
पहले एक प्राथमिक कुंजी के साथ एक तालिका बनाएं जिसमें 1 से 10000 तक पूर्णांक हैं:
CREATE TABLE N_10000 (NUM_ID INTEGER NOT NULL, PRIMARY KEY (NUM_ID));
INSERT /*+APPEND */ INTO N_10000
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 10000
ORDER BY LEVEL;
COMMIT;
निम्न क्वेरी पर विचार करें जो दो व्युत्पन्न तालिकाओं का उपयोग करती है:
SELECT t1.NUM_ID
FROM
(
SELECT n1.NUM_ID
FROM N_10000 n1
CROSS JOIN N_10000 n2
) t1
LEFT OUTER JOIN
(
SELECT n1.NUM_ID
FROM N_10000 n1
CROSS JOIN N_10000 n2
) t2 ON t1.NUM_ID = t2.NUM_ID
WHERE t1.NUM_ID <= 0;
हम इस क्वेरी को देख सकते हैं और जल्दी से निर्धारित कर सकते हैं कि यह किसी भी पंक्तियों को वापस नहीं करेगा। ओरेकल को यह निर्धारित करने के लिए इंडेक्स का उपयोग करने में सक्षम होना चाहिए। मेरी मशीन पर क्वेरी निम्न योजना के साथ लगभग तुरंत समाप्त होती है:
मुझे खुद को दोहराना पसंद नहीं है, इसलिए चलिए CTE के साथ एक ही क्वेरी की कोशिश करते हैं:
WITH N_10000_CTE AS (
SELECT n1.NUM_ID
FROM N_10000 n1
CROSS JOIN N_10000 n2
)
SELECT t1.NUM_ID
FROM N_10000_CTE t1
LEFT JOIN N_10000_CTE t2 ON t1.NUM_ID = t2.NUM_ID
WHERE t1.NUM_ID <= 0;
यहाँ योजना है:
यह वास्तव में एक बुरी योजना है। इंडेक्स का उपयोग करने के बजाय, ओरेकल 10000 X 10000 = 100000000 पंक्तियों को एक अस्थायी तालिका में केवल 0 पंक्तियों को वापस करने के लिए उत्प्रेरित करता है। इस योजना की लागत लगभग 6 M है जो अन्य क्वेरी की तुलना में बहुत अधिक है। क्वेरी को मेरी मशीन पर समाप्त होने में 68 सेकंड लगे।
ध्यान दें कि यदि अस्थायी तालिकाओं में पर्याप्त मेमोरी या खाली स्थान नहीं है तो क्वेरी विफल हो सकती है।
मैं INLINE
CTE को उत्प्रेरित करने से ऑप्टिमाइज़र को हटाने के लिए अनिर्धारित संकेत का उपयोग कर सकता हूं :
WITH N_10000_CTE AS (
SELECT /*+ INLINE */ n1.NUM_ID
FROM N_10000 n1
CROSS JOIN N_10000 n2
)
SELECT t1.NUM_ID
FROM N_10000_CTE t1
LEFT JOIN N_10000_CTE t2 ON t1.NUM_ID = t2.NUM_ID
WHERE t1.NUM_ID <= 0;
वह क्वेरी इंडेक्स का उपयोग करने में सक्षम है और लगभग तुरंत खत्म कर देता है। क्वेरी की लागत पहले की तरह 11. है, इसलिए दूसरी क्वेरी के लिए, ओरेकल द्वारा उपयोग किए जाने वाले हेयुरिस्टिक ने इसका परिणाम दिया, जिसमें क्वेरी की बजाय 11 की अनुमानित लागत के साथ 6 एम की अनुमानित लागत के साथ एक क्वेरी चुना गया था।
WITH...
) हैं। आप एक CTE के रूप में हर व्युत्पन्न तालिका को फिर से लिख सकते हैं, लेकिन शायद दूसरा तरीका राउंड (उदाहरण के लिए CTE या CTE का कई बार उपयोग करना)