यह कार्डिनैलिटी का अनुमान इतना बड़ा क्यों है?


18

मैं अनुभव कर रहा हूं कि मुझे क्या लगता है कि निम्नलिखित प्रश्न के लिए एक अत्यधिक उच्च कार्डिनैलिटी अनुमान है:

SELECT dm.PRIMARY_ID
FROM
(
    SELECT COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID) PRIMARY_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
) dm
INNER JOIN X_LAST_TABLE lst ON dm.PRIMARY_ID = lst.JOIN_ID;

अनुमानित योजना यहाँ है । मैं तालिकाओं की एक आँकड़े प्रति पर काम कर रहा हूँ ताकि मैं एक वास्तविक योजना को शामिल न कर सकूँ। हालाँकि, मुझे नहीं लगता कि यह इस समस्या के लिए बहुत प्रासंगिक है।

SQL सर्वर का अनुमान है कि 481577 पंक्तियों को "डीएम" व्युत्पन्न तालिका से वापस किया जाएगा। इसके बाद अनुमान है कि X_LAST_TABLE में शामिल होने के बाद 4528030000 पंक्तियों को वापस कर दिया जाएगा, लेकिन JOIN_ID X_LAST_TIME की प्राथमिक कुंजी है। मैं 0 और 481577 पंक्तियों के बीच एक कार्डिनैलिटी अनुमान शामिल होने की उम्मीद करूंगा। इसके बजाय, पंक्ति अनुमान उन पंक्तियों की संख्या का 10% प्रतीत होता है जो मुझे तब मिलती हैं जब बाहरी और आंतरिक तालिकाओं में शामिल हो जाती हैं। इसके लिए गणित गोलाई के साथ काम करता है: 481577 * 94025 * 0.1 = 45280277425 जो कि 4528030000 तक गोल है।

मैं मुख्य रूप से इस व्यवहार के मूल कारण की तलाश में हूं। मैं साधारण वर्कअराउंड में भी दिलचस्पी रखता हूं, लेकिन कृपया डेटा मॉडल बदलने या अस्थायी तालिकाओं का उपयोग करने का सुझाव न दें। यह क्वेरी एक दृश्य के भीतर तर्क का सरलीकरण है। मुझे पता है कि कुछ स्तंभों पर COALESCE करना और उन पर जुड़ना एक अच्छा अभ्यास नहीं है। इस प्रश्न के लक्ष्य का एक हिस्सा यह पता लगाना है कि क्या मुझे डेटा मॉडल को फिर से डिज़ाइन करने की अनुशंसा करने की आवश्यकता है।

मैं Microsoft SQL सर्वर 2014 पर लीगेसी कार्डिनैलिटी एसेलेटर सक्षम के साथ परीक्षण कर रहा हूं। टीएफ 4199 और अन्य चालू हैं। मैं ट्रेस झंडे की एक पूरी सूची दे सकता हूं अगर वह प्रासंगिक हो।

यहाँ सबसे अधिक प्रासंगिक तालिका परिभाषा है:

CREATE TABLE X_LAST_TABLE (
JOIN_ID NUMERIC(18, 0) NOT NULL
    CONSTRAINT PK_X_LAST_TABLE PRIMARY KEY CLUSTERED (JOIN_ID ASC)
);

अगर मैं किसी को भी अपने सर्वर पर समस्या को पुन: उत्पन्न करना चाहता हूं, तो मैंने उनके आंकड़ों के साथ-साथ सभी तालिका निर्माण स्क्रिप्ट को भी स्क्रिप्ट किया

मेरी कुछ टिप्पणियों को जोड़ने के लिए, TF 2312 का उपयोग अनुमान को ठीक करता है, लेकिन यह मेरे लिए कोई विकल्प नहीं है। TF 2301 अनुमान को ठीक नहीं करता है। तालिकाओं में से एक को हटाने से अनुमान ठीक हो जाता है। विचित्र रूप से, X_DETAIL_LINK के सम्मिलित आदेश को बदलने से भी अनुमान ठीक हो जाता है। ज्वाइन ऑर्डर बदलने से मेरा मतलब है कि क्वेरी को फिर से लिखना और जॉइंट ऑर्डर को एक हिंट के साथ मजबूर न करना। यहाँ एक अनुमानित क्वेरी प्लान है जब सिर्फ जॉन्स का क्रम बदल रहा है।


PS यदि आप किसी भी तरह से स्विच कर सकते bigintहैं decimal(18, 0)तो आपको लाभ मिलेगा: 1) प्रत्येक मूल्य के लिए 9 के बजाय 8 बाइट्स का उपयोग करें, और 2) पैक डेटा प्रकार के बजाय बाइट-तुलनीय डेटा प्रकार का उपयोग करें, जिसके निहितार्थ हो सकते हैं मूल्यों की तुलना करते समय CPU समय के लिए।
एरिक

@ एरिक टिप के लिए धन्यवाद, लेकिन मुझे पहले से ही पता था। दुर्भाग्य से हम विरासत कारणों से BUMINT से अधिक NUMERIC (18,0) के साथ फंस गए हैं।
जो ओबिश

यह एक शॉट के लायक था!
एरिक

यदि आपको अशक्त नहीं है, तो क्या आपको X_DETAIL2और X_DETAIL3तालिकाओं की आवश्यकता JOIN_IDहै X_DETAIL1?
एरिक

@ एरिक यह एक MCVE है, तो इस बिंदु पर क्वेरी बिल्कुल समझ में नहीं आता है।
जो ओबिश

जवाबों:


14

मुझे पता है कि 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विदेशी कुंजी और अन्य बाधाओं क्वेरी संकलन के लिए उपयोगी है, और आदर्श।


10

मेरा मानना ​​है कि शामिल होने के कारण Compute Scalarऑपरेटर समस्या का मूल कारण है। ऐतिहासिक रूप से, गणना करने वाले स्केल को 1 , 2 की सही लागत देना मुश्किल है ।COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID)X_LAST_TABLE.JOIN_ID

चूँकि आपने सटीक आँकड़ों के साथ एक न्यूनतम पूर्ण सत्यापन योग्य उदाहरण (धन्यवाद!) प्रदान किया है, मैं क्वेरी को फिर से लिखने में सक्षम हूँ जैसे कि जुड़ने के लिए अब उस CASEकार्यक्षमता की आवश्यकता नहीं है जिसे COALESCEविस्तारित किया गया है, जिसके परिणामस्वरूप बहुत अधिक सटीक पंक्ति अनुमान और जाहिर तौर पर और अधिक सटीक समग्र लागत अंत में परिशिष्ट देखें। :

SELECT COALESCE(dm.d1ID, dm.d2ID, dm.d3ID)
FROM
(
    SELECT d1ID = d1.JOIN_ID
        , d2ID = d2.JOIN_ID
        , d3ID = 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
) dm
INNER JOIN X_LAST_TABLE lst 
    ON (dm.d1ID IS NOT NULL AND dm.d1ID = lst.JOIN_ID)
    OR (dm.d1ID IS NULL AND dm.d2ID IS NOT NULL AND dm.d2ID = lst.JOIN_ID)
    OR (dm.d1ID IS NULL AND dm.d2ID IS NULL AND dm.d3ID IS NOT NULL AND dm.d3ID = lst.JOIN_ID);

जबकि xID IS NOT NULLतकनीकी रूप से इसकी आवश्यकता नहीं है, क्योंकि यह ID = JOIN_IDअशक्त मूल्यों पर शामिल नहीं होगा, मैंने उन्हें शामिल किया क्योंकि यह अधिक स्पष्ट रूप से इरादे को चित्रित करता है।

योजना 1 और योजना 2

योजना 1:

यहां छवि विवरण दर्ज करें

योजना 2:

यहां छवि विवरण दर्ज करें

नई क्वेरी लाभ (?) के समानांतरकरण से। नोट के अलावा, नई क्वेरी में 1 की पंक्तियों की अनुमानित आउटपुट संख्या है, जो वास्तव में मूल क्वेरी के लिए 4528030000 के अनुमान की तुलना में दिन के अंत में खराब हो सकती है। नई क्वेरी पर चयनित ऑपरेटर के लिए उप-लागत 243210 पर आती है, जबकि मूल घड़ियां 536.535 पर, जो स्पष्ट रूप से कम है। ऐसा कहने के बाद, मेरा मानना ​​है कि पहला अनुमान कहीं भी वास्तविकता के करीब नहीं है।


परिशिष्ट 1।

हीप ™ पर विभिन्न लोगों के साथ विचार-विमर्श के बाद @Lamak के साथ चर्चा के बाद, ऐसा लगता है कि ऊपर मेरी अवलोकन क्वेरी बहुत अच्छा करती है, यहां तक ​​कि समानता के साथ भी। एक समाधान जो अच्छे प्रदर्शन और अच्छे कार्डिनैलिटी अनुमान दोनों की अनुमति देता है, जैसे कि ए , के COALESCE(x,y,z)साथ प्रतिस्थापित होता ISNULL(ISNULL(x, y), z)है:

SELECT dm.PRIMARY_ID
FROM
(
    SELECT ISNULL(ISNULL(d1.JOIN_ID, d2.JOIN_ID), d3.JOIN_ID) PRIMARY_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
) dm
INNER JOIN X_LAST_TABLE lst ON dm.PRIMARY_ID = lst.JOIN_ID;

COALESCECASEक्वेरी ऑप्टिमाइज़र द्वारा "कवर के तहत" एक बयान में तब्दील हो जाता है । जैसे, कार्डिनैलिटी अनुमानक के पास अंदर दफन स्तंभों के लिए विश्वसनीय आंकड़ों की खोज करने में कठिन समय है COALESCEISNULLकार्डिनलिटी अनुमानक के लिए एक आंतरिक कार्य अधिक "खुला" है। यह भी लायक नहीं है कि ISNULLअगर लक्ष्य को अशक्त होने के लिए जाना जाता है तो इसे दूर किया जा सकता है।

ISNULLवैरिएंट की योजना इस प्रकार है:

यहां छवि विवरण दर्ज करें

( यहां योजना संस्करण पेस्ट करें )।

FYI करें, उनके शानदार प्लान एक्सप्लोरर के लिए सेंट्री वन को प्रस्तावित करता है , जिसका उपयोग मैं ऊपर चित्रमय योजनाओं का उत्पादन करने के लिए करता था।


-1

आपकी सम्मिलित स्थिति के अनुसार, तालिका को इतने सारे शिष्टाचार में व्यवस्थित किया जा सकता है, जो "एक विशेष तरीके से बदल रहा है" परिणाम को ठीक करता है।

मान लीजिए कि केवल एक तालिका में शामिल होने से आपको सही परिणाम मिलता है।

SELECT COALESCE(d1.JOIN_ID, d2.JOIN_ID, d3.JOIN_ID) PRIMARY_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

यहाँ के स्थान पर X_DETAIL_1, आप X_DETAIL_2या तो उपयोग कर सकते हैं या X_DETAIL_3

इसलिए बाकी 2 तालिकाओं का उद्देश्य स्पष्ट नहीं है।

यह ऐसा है जैसे आपने टेबल X_DETAIL_1को 2 और भागों में तोड़ दिया है ।

सबसे अधिक शायद " त्रुटि है जहां आप उन तालिकाओं को आबाद कर रहे हैं। " आदर्श रूप X_DETAIL_1से X_DETAIL_2, और X_DETAIL_3इसमें समान मात्रा में पंक्तियां होनी चाहिए।

लेकिन एक या अधिक तालिका में अवांछित पंक्तियों की संख्या होती है।

क्षमा करें यदि मैं गलत हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.