मुझे पता है कि COALESCE
कुछ स्तंभों पर काम करना और उन पर जुड़ना एक अच्छा अभ्यास नहीं है।
स्कीमा 3NF + (कुंजियों और बाधाओं के साथ) होने पर अच्छी कार्डिनैलिटी और वितरण अनुमान लगाना काफी कठिन होता है और क्वेरी संबंधपरक और मुख्य रूप से SPJG (चयन-प्रोजेक्शन-जॉइन-ग्रुप बाय) होती है। सीई मॉडल उन सिद्धांतों पर बनाया गया है। एक क्वेरी में जितनी अधिक असामान्य या गैर-संबंधपरक विशेषताएं हैं, कार्डिनिटी और चयनात्मकता की रूपरेखा क्या संभाल सकती है, इसकी सीमाओं के करीब पहुंच जाती है। बहुत दूर जाओ और CE अनुमान लगाएगा ।
MCVE उदाहरण के अधिकांश सरल SPJ (नहीं जी) है, मुख्य रूप से बाहरी समान के साथ यद्यपि (आंतरिक रूप से शामिल होने के साथ-साथ विरोधी अर्धविराम के रूप में) सरल आंतरिक समरूप (या अर्धविराम) के बजाय। सभी संबंधों में चाबियाँ हैं, हालांकि कोई विदेशी कुंजी या अन्य बाधाएं नहीं हैं। सभी में से एक जोड़ एक-से-कई हैं, जो अच्छा है।
अपवाद कई-से-कई बाहरी जुड़ने के बीच X_DETAIL_1
और है X_DETAIL_LINK
। MCVE में शामिल होने का एकमात्र कार्य संभावित रूप से डुप्लिकेट पंक्तियों में है X_DETAIL_1
। यह एक असामान्य चीज है।
सरल समानता भविष्यवाणी (चयन) और स्केलर ऑपरेटर भी बेहतर है। उदाहरण के लिए विशेषता की तुलना-समान विशेषता / निरंतरता सामान्य रूप से मॉडल में अच्छी तरह से काम करती है। ऐसे विधेयकों के अनुप्रयोग को प्रतिबिंबित करने के लिए हिस्टोग्राम और आवृत्ति आंकड़ों को संशोधित करना अपेक्षाकृत "आसान" है।
COALESCE
पर बनाया गया है CASE
, जो बदले में आंतरिक रूप से लागू किया गया है IIF
(और यह IIF
लेन-देन-SQL भाषा में दिखाई देने से पहले सच था )। सीई मॉडल IIF
एक के रूप में UNION
दो परस्पर अनन्य बच्चों के साथ, प्रत्येक इनपुट संबंध पर एक चयन पर एक परियोजना से मिलकर। सूचीबद्ध घटकों में से प्रत्येक में मॉडल का समर्थन है, इसलिए उन्हें संयोजन करना अपेक्षाकृत सरल है। फिर भी, अधिक परतें अमूर्त होती हैं, कम सटीक अंतिम परिणाम होता है - यही कारण है कि बड़ी निष्पादन योजनाएं कम स्थिर और विश्वसनीय होती हैं।
ISNULL
दूसरी ओर, है इंजन के लिए आंतरिक है। यह किसी भी अधिक बुनियादी घटकों का उपयोग करके नहीं बनाया गया है। ISNULL
उदाहरण के लिए, हिस्टोग्राम के प्रभाव को लागू करना , NULL
मूल्यों के लिए कदम की जगह के रूप में सरल है (और आवश्यक के रूप में कॉम्पैक्ट करना)। यह अभी भी अपेक्षाकृत अपारदर्शी है, जैसा कि स्केलर ऑपरेटर चलते हैं, और जहां संभव हो, इसलिए सबसे अच्छा बचा जाता है। फिर भी, यह आम तौर पर एक CASE
वैकल्पिक विकल्प की तुलना में अधिक अनुकूलक-अनुकूल (कम ऑप्टिमाइज़र-अमित्र) बोल रहा है ।
SQL सर्वर मानकों द्वारा भी CE (70 और 120+) बहुत जटिल है। यह प्रत्येक ऑपरेटर को सरल तर्क (एक गुप्त सूत्र के साथ) लागू करने का मामला नहीं है। CE चाबियाँ और कार्यात्मक निर्भरता के बारे में जानता है; यह जानता है कि आवृत्तियों, बहुभिन्नरूपी आंकड़ों और हिस्टोग्राम का उपयोग करने का अनुमान कैसे लगाया जाता है; और विशेष मामलों, परिशोधन, जांच और संतुलन, और सहायक संरचनाओं का एक पूर्ण टन है। यह अक्सर अनुमान लगाता है जैसे कई तरीकों से जुड़ता है (आवृत्ति, हिस्टोग्राम) और दोनों के बीच के अंतर के आधार पर एक परिणाम या समायोजन का फैसला करता है।
कवर करने के लिए एक अंतिम मूल बात: क्वेरी ट्री में हर ऑपरेशन के लिए प्रारंभिक कार्डिनैलिटी का अनुमान नीचे से ऊपर तक चलता है। पत्ती संचालकों के लिए पहले (आधार संबंध) के लिए चयनात्मकता और कार्डिनैलिटी व्युत्पन्न होती है। संशोधित हिस्टोग्राम और घनत्व / आवृत्ति की जानकारी मूल संचालकों के लिए ली गई है। हम जिस पेड़ पर जाते हैं, अनुमानों की गुणवत्ता उतनी ही कम होती जाती है, क्योंकि त्रुटियां जमा होती जाती हैं।
यह एकल प्रारंभिक व्यापक अनुमान एक प्रारंभिक बिंदु प्रदान करता है, और किसी अंतिम विचार योजना को दिए जाने से पहले अच्छी तरह से होता है (यह एक तरह से तुच्छ योजना संकलन चरण से पहले भी होता है)। इस बिंदु पर क्वेरी ट्री क्वेरी के लिखित रूप को काफी बारीकी से दर्शाती है (हालांकि हटाए गए उपश्रेणियों और लागू किए गए सरलीकरण के साथ)।
प्रारंभिक आकलन के तुरंत बाद, SQL सर्वर पुनरावृत्ति में शामिल होने के लिए जनांकिकीय कार्य करता है, जो कि कम बोलने से पेड़ को छोटे तालिकाओं में रखने का प्रयास करता है और उच्च-चयनात्मकता पहले मिलती है। यह बाहरी जॉइन और क्रॉस उत्पादों से पहले इनर जॉइन करने की कोशिश करता है। इसकी क्षमताएं व्यापक नहीं हैं; इसके प्रयास संपूर्ण नहीं हैं; और यह भौतिक लागतों पर विचार नहीं करता है (क्योंकि वे अभी तक मौजूद नहीं हैं - केवल सांख्यिकीय जानकारी और मेटाडेटा जानकारी मौजूद हैं)। Heuristic reorder सरल आंतरिक सम-विषम पेड़ों पर सबसे सफल है। यह लागत-आधारित अनुकूलन के लिए "बेहतर" शुरुआती बिंदु प्रदान करने के लिए मौजूद है।
यह कार्डिनैलिटी का अनुमान इतना बड़ा क्यों है?
MCVE में एक "असामान्य" अधिकतर-बेमानी कई-से-कई सम्मिलित होते हैं, और एक समान COALESCE
विधेय में शामिल होते हैं । ऑपरेटर ट्री में अंतिम रूप से एक आंतरिक जुड़ाव भी होता है , जिसे पुनरावृत्ति में शामिल होने वाला पुन: पेड़ पेड़ को अधिक पसंदीदा स्थिति में ले जाने में असमर्थ था। सभी स्केल और अनुमानों को छोड़कर, पेड़ शामिल है:
LogOp_Join [ Card=4.52803e+009 ]
LogOp_LeftOuterJoin [ Card=481577 ]
LogOp_LeftOuterJoin [ Card=481577 ]
LogOp_LeftOuterJoin [ Card=481577 ]
LogOp_LeftOuterJoin [ Card=481577 ]
LogOp_Get TBL: X_DRIVING_TABLE(alias TBL: dt) [ Card=481577 ]
LogOp_Get TBL: X_DETAIL_1(alias TBL: d1) [ Card=70 ]
LogOp_Get TBL: X_DETAIL_LINK(alias TBL: lnk) [ Card=47 ]
LogOp_Get TBL: X_DETAIL_2(alias TBL: d2) X_DETAIL_2 [ Card=119 ]
LogOp_Get TBL: X_DETAIL_3(alias TBL: d3) X_DETAIL_3 [ Card=281 ]
LogOp_Get TBL: X_LAST_TABLE(alias TBL: lst) X_LAST_TABLE [ Card=94025 ]
ध्यान दें कि दोषपूर्ण अंतिम अनुमान पहले से ही है। इसे Card=4.52803e+009
डबल परिशुद्धता फ्लोटिंग पॉइंट मान 4.5280277425e + 9 (दशमलव में 4528027742.5) के रूप में आंतरिक रूप से संग्रहीत और संग्रहीत किया जाता है।
मूल क्वेरी में व्युत्पन्न तालिका हटा दी गई है, और अनुमान सामान्यीकृत हैं। पेड़ का एक एसक्यूएल प्रतिनिधित्व जिस पर प्रारंभिक कार्डिनैलिटी और चयनात्मकता अनुमान लगाया गया था:
SELECT
PRIMARY_ID = COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID)
FROM X_DRIVING_TABLE dt
LEFT OUTER JOIN X_DETAIL_1 d1
ON dt.ID = d1.ID
LEFT OUTER JOIN X_DETAIL_LINK lnk
ON d1.LINK_ID = lnk.LINK_ID
LEFT OUTER JOIN X_DETAIL_2 d2
ON dt.ID = d2.ID
LEFT OUTER JOIN X_DETAIL_3 d3
ON dt.ID = d3.ID
INNER JOIN X_LAST_TABLE lst
ON lst.JOIN_ID = COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID)
(एक तरफ के रूप में, दोहराया COALESCE
भी अंतिम योजना में मौजूद है - एक बार अंतिम गणना स्केलर में, और एक बार आंतरिक जुड़ाव के भीतर)।
फाइनल जॉइन की सूचना दें। यह आंतरिक जुड़ाव (परिभाषा के अनुसार) के कार्टेशियन उत्पाद X_LAST_TABLE
और पूर्ववर्ती ज्वाइन आउटपुट है, जिसमें सेलेक्ट किया हुआ (प्रेडिकेटेट शामिल है) lst.JOIN_ID = COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID)
। कार्टेशियन उत्पाद की कार्डिनैलिटी केवल 481577 * 94025 = 45280277425 है।
उसके लिए, हमें विधेय की चयनात्मकता निर्धारित करने और लागू करने की आवश्यकता है। अपारदर्शी विस्तार के संयोजन COALESCE
पेड़ (के मामले में UNION
और IIF
, याद) एक साथ महत्वपूर्ण जानकारी पर प्रभाव के साथ, व्युत्पन्न हिस्टोग्राम और पहले 'असामान्य' ज्यादातर-अनावश्यक कई-से-अनेक बाहरी की आवृत्तियों संयुक्त साधन में शामिल होने के सीई करने में असमर्थ है किसी भी सामान्य तरीके से स्वीकार्य अनुमान प्राप्त करें।
नतीजतन, यह अनुमान तर्क में प्रवेश करता है। अनुमान तर्क मध्यम रूप से जटिल है, "शिक्षित" अनुमान की परतों के साथ और "नहीं-तो शिक्षित" अनुमान एल्गोरिदम की कोशिश की। यदि किसी अनुमान का कोई बेहतर आधार नहीं मिलता है, तो मॉडल अंतिम उपाय के अनुमान का उपयोग करता है, जो कि समानता की तुलना के लिए है: sqllang!x_Selectivity_Equal
= निश्चित 0.1 चयनात्मकता (10% अनुमान):
-- the moment of doom
movsd xmm0,mmword ptr [sqllang!x_Selectivity_Equal
परिणाम कार्टेशियन उत्पाद पर 0.1 चयनात्मकता है: 481577 * 94025 * 0.1 = 4528027742.5 (~ 4.52803e + 009) जैसा कि पहले उल्लेख किया गया है।
पुनर्लेखन
जब समस्याग्रस्त जुड़ाव पर टिप्पणी की जाती है , तो एक बेहतर अनुमान उत्पन्न होता है क्योंकि निश्चित-चयनात्मकता "अंतिम उपाय का अनुमान" से बचा जाता है (महत्वपूर्ण जानकारी 1-एम जॉइन द्वारा बरकरार रखी जाती है)। अनुमान की गुणवत्ता अभी भी कम आत्मविश्वास की है, क्योंकि एक COALESCE
सम्मिलित विधेय सभी सीई के अनुकूल नहीं है। संशोधित अनुमान कम से कम करता नज़र मनुष्य के लिए अधिक उचित है, मुझे लगता।
जब क्वेरी को X_DETAIL_LINK
अंतिम सम्मिलित करने के लिए बाहरी जॉइन के साथ लिखा जाता है , तो हेयुरिस्टिक रीऑर्डर इसे अंतिम इनर जॉइन के साथ स्वैप करने में सक्षम होता है X_LAST_TABLE
। बाहरी जुड़ने को समस्या के ठीक बगल में रखना बाहरी जुड़ाव को सीमित करने की प्रारंभिक क्षमताओं को अंतिम अनुमान में सुधार करने का अवसर देता है, क्योंकि ज्यादातर अतिरेकपूर्ण "असामान्य" के प्रभाव से कई-से-कई बाहरी जुड़ाव मुश्किल चयनात्मकता अनुमान के बाद आते हैं। के लिए COALESCE
। फिर, अनुमान निश्चित अनुमानों से थोड़ा बेहतर है, और शायद कानून की अदालत में निर्धारित क्रॉस-परीक्षा के लिए खड़े नहीं होंगे।
आंतरिक और बाहरी जुड़नों के मिश्रण को पुन: व्यवस्थित करना कठिन और समय लेने वाला है (यहां तक कि चरण 2 पूर्ण अनुकूलन केवल सैद्धांतिक चालों के सीमित सबसेट का प्रयास करता है)।
ISNULL
मैक्स वर्नन के उत्तर में सुझाए गए नेस्टेड को जमानत-आउट निश्चित अनुमान से बचने का प्रबंधन करता है, लेकिन अंतिम अनुमान एक असंभव शून्य पंक्तियां हैं (शालीनता के लिए एक पंक्ति में उत्थान)। यह सभी सांख्यिकीय आधार पर गणना के लिए 1 पंक्ति का एक निश्चित अनुमान हो सकता है।
मैं 0 और 481577 पंक्तियों के बीच एक कार्डिनैलिटी अनुमान शामिल होने की उम्मीद करूंगा।
यह एक उचित उम्मीद है, भले ही कोई यह स्वीकार करे कि शारीरिक रूप से भिन्न होने पर कार्डिनैलिटी का अनुमान अलग-अलग समय पर (लागत-आधारित अनुकूलन के दौरान) हो सकता है, लेकिन तार्किक रूप से और शब्दार्थ समान उपप्रकार - अंतिम योजना के साथ एक तरह का सिले-सिला हुआ है। सर्वोत्तम (प्रति मेमो समूह)। एक योजना-व्यापक स्थिरता की गारंटी की कमी का मतलब यह नहीं है कि एक व्यक्तिगत जुड़ाव सम्मानीयता को प्रवाहित करने में सक्षम होना चाहिए, मुझे वह मिलता है।
दूसरी ओर, यदि हम अंतिम उपाय के अनुमान पर समाप्त होते हैं, तो आशा पहले से ही खो गई है, इसलिए परेशान क्यों हैं। हमने उन सभी चालों की कोशिश की जिन्हें हम जानते थे, और त्याग दिया। यदि और कुछ नहीं, तो जंगली अंतिम अनुमान एक महान चेतावनी संकेत है कि इस क्वेरी के संकलन और अनुकूलन के दौरान सीई के अंदर सब कुछ ठीक नहीं हुआ।
जब मैंने MCVE की कोशिश की, तो 120+ CE ने ISNULL
मूल क्वेरी के लिए एक शून्य (= 1) पंक्ति अंतिम अनुमान (जैसे नेस्टेड ) का उत्पादन किया, जो मेरे सोचने के तरीके के लिए अस्वीकार्य है।
वास्तविक समाधान शायद एक डिजाइन बदलाव शामिल है, सरल बिना सम मिलती अनुमति देने के लिए COALESCE
या ISNULL
विदेशी कुंजी और अन्य बाधाओं क्वेरी संकलन के लिए उपयोगी है, और आदर्श।
bigint
हैंdecimal(18, 0)
तो आपको लाभ मिलेगा: 1) प्रत्येक मूल्य के लिए 9 के बजाय 8 बाइट्स का उपयोग करें, और 2) पैक डेटा प्रकार के बजाय बाइट-तुलनीय डेटा प्रकार का उपयोग करें, जिसके निहितार्थ हो सकते हैं मूल्यों की तुलना करते समय CPU समय के लिए।