एसक्यूएल सर्वर का मूल्यांकन करने के लिए अनुमति दी है A <> B
के रूप में A < B OR A > B
, भले ही भाव से एक गैर नियतात्मक है?
यह कुछ हद तक विवादास्पद बिंदु है, और इसका उत्तर एक योग्य "हाँ" है।
सबसे अच्छी चर्चा जो मुझे पता है कि नईआईडी और टेबल एक्सप्रेशंस के साथ इत्ज़िक बेन-गण की कनेक्ट बग रिपोर्ट बग के जवाब में दी गई थी , जिसे ठीक नहीं किया गया था। कनेक्ट के बाद से सेवानिवृत्त हो गया है, इसलिए वहाँ लिंक एक वेब संग्रह के लिए है। अफसोस की बात है कि कनेक्ट के निधन से कई उपयोगी सामग्री खो गई थी (या खोजने के लिए कठिन बना दिया गया था)। वैसे भी, Microsoft के जिम हॉग के सबसे उपयोगी उद्धरण हैं:
इस मुद्दे के बहुत हिट करने के लिए हिट - अनुकूलन एक कार्यक्रम के शब्दार्थ को बदलने की अनुमति है? Ie: यदि कोई प्रोग्राम कुछ उत्तरों की पैदावार करता है, लेकिन धीरे-धीरे चलता है, तो क्या यह क्वेरी ऑप्टिमाइज़र के लिए वैध है कि वह प्रोग्राम तेजी से चलाए, फिर भी दिए गए परिणामों को बदल दें?
"नहीं!" चिल्लाने से पहले (मेरा अपना व्यक्तिगत झुकाव भी :-), विचार करें: अच्छी खबर यह है कि, 99% मामलों में, उत्तर समान हैं। इसलिए क्वेरी ऑप्टिमाइज़ेशन एक स्पष्ट जीत है। बुरी खबर यह है कि, यदि क्वेरी में साइड-इफ़ेक्टिंग कोड शामिल है, तो विभिन्न योजनाएँ वास्तव में अलग-अलग परिणाम दे सकती हैं। और NEWID () एक ऐसा साइड-इफ़ेक्टिंग (गैर-नियतात्मक) 'फ़ंक्शन' है जो अंतर को उजागर करता है। [वास्तव में, यदि आप प्रयोग करते हैं, तो आप दूसरों को समर्पित कर सकते हैं - उदाहरण के लिए, AND क्लॉज का शॉर्ट-सर्किट मूल्यांकन: दूसरा क्लॉज एक अंकगणितीय फूट डालो-शून्य को बनाओ - विभिन्न अनुकूलन कर सकते हैं निष्पादित करें कि दूसरा क्लॉज पहले क्लॉज से पहले हो] क्रेग की व्याख्या, इस धागे में कहीं और, कि स्क्लर ऑपरेटर्स द्वारा निष्पादित किए जाने पर SqlServer गारंटी नहीं देता है।
इसलिए, हमारे पास एक विकल्प है: यदि हम गैर-नियतात्मक (साइड-इफ़ेक्टिंग) कोड की उपस्थिति में एक निश्चित व्यवहार की गारंटी देना चाहते हैं - ताकि जॉइन के परिणाम, उदाहरण के लिए, नेस्टेड-लूप निष्पादन के शब्दार्थ का पालन करें - हम उस व्यवहार को लागू करने के लिए उपयुक्त विकल्प का उपयोग कर सकते हैं - जैसा कि यूसी बताते हैं। लेकिन परिणामी कोड धीमी गति से चलेगा - यह लागत की है, प्रभाव में, क्वेरी ऑप्टिमाइज़र की हॉबीलिंग।
उस सभी ने कहा, हम क्वेरी ऑप्टिमाइज़र को NEWID के लिए "अपेक्षित" व्यवहार की दिशा में ले जा रहे हैं () - "अपेक्षित रूप से परिणाम" के लिए प्रदर्शन बंद कर रहे हैं।
समय के साथ इस संबंध में व्यवहार के बदलाव का एक उदाहरण NULLIF गैर-नियतात्मक कार्यों जैसे कि RAND () के साथ गलत तरीके से काम करता है । वहाँ भी इसी तरह के अन्य मामलों में उपयोग कर रहे हैं जैसे COALESCE
कि एक उपश्रेणी के साथ जो अप्रत्याशित परिणाम उत्पन्न कर सकते हैं, और जिन्हें धीरे-धीरे संबोधित भी किया जा रहा है।
जिम जारी है:
पुनर्चक्रण करना । । । मैंने देव टीम के साथ इस सवाल पर चर्चा की है। और अंततः हमने निम्नलिखित कारणों से वर्तमान व्यवहार को नहीं बदलने का फैसला किया है:
1) ऑप्टिमाइज़र स्केलर फ़ंक्शंस के निष्पादन की समय या संख्या की गारंटी नहीं देता है। यह एक लंबे समय से स्थाई कार्यकाल है। यह मौलिक 'लेवे' था, ऑप्टिमाइज़र को क्वेरी-प्लान निष्पादन में महत्वपूर्ण सुधार प्राप्त करने की पर्याप्त स्वतंत्रता देता है।
2) यह "एक बार प्रति-पंक्ति व्यवहार" एक नया मुद्दा नहीं है, हालांकि यह व्यापक रूप से चर्चा में नहीं है। हमने इसके व्यवहार को युकॉन रिलीज़ में वापस लाना शुरू कर दिया। लेकिन सभी मामलों में सटीक रूप से पिन करना काफी कठिन है, वास्तव में इसका क्या मतलब है! उदाहरण के लिए, क्या यह अंतिम परिणाम के लिए 'रास्ते में गणना की गई पंक्तियों को अंतरिम करने के लिए लागू होता है?' - किस मामले में यह स्पष्ट रूप से चुनी गई योजना पर निर्भर करता है। या यह केवल उन पंक्तियों पर लागू होता है जो अंततः पूर्ण परिणाम में दिखाई देंगे? - यहाँ एक बुरा पुनरावर्तन चल रहा है, जैसा कि मुझे यकीन है कि आप सहमत होंगे!
3) जैसा कि मैंने पहले उल्लेख किया है, हम "प्रदर्शन का अनुकूलन" करने के लिए डिफ़ॉल्ट हैं - जो कि 99% मामलों के लिए अच्छा है। 1% मामलों में, जहां परिणाम बदल सकते हैं - स्पॉट-इफ़ेक्टिंग 'फ़ंक्शंस' जैसे कि NEWID - और 'फ़िक्स' के लिए आसान (परिणाम के रूप में ट्रेडिंग पूर्ण) के लिए काफी आसान है। यह डिफ़ॉल्ट "प्रदर्शन को अनुकूलित करने" के लिए फिर से, लंबे समय से स्थापित है, और स्वीकार किया जाता है। (हां, यह पारंपरिक प्रोग्रामिंग भाषाओं के लिए कंपाइलरों द्वारा चुना गया रुख नहीं है, लेकिन ऐसा ही हो)।
तो, हमारी सिफारिशें हैं:
क) गैर-गारंटीकृत समय और संख्या-निष्पादन के अर्थ-विज्ञान पर निर्भरता से बचें। ख) टेबल के भावों में डीप न्यूड () का उपयोग करने से बचें। ग) एक विशेष व्यवहार (ट्रेडिंग पूर्ण) को लागू करने के लिए विकल्प का उपयोग करें
आशा है कि यह स्पष्टीकरण "बग को ठीक नहीं करेगा" के रूप में इस बग को बंद करने के हमारे कारणों को स्पष्ट करने में मदद करता है।
दिलचस्प है, AND NOT (s_guid = NEWID())
एक ही निष्पादन योजना की पैदावार
यह सामान्यीकरण का परिणाम है, जो क्वेरी संकलन के दौरान बहुत पहले होता है। दोनों अभिव्यक्तियाँ बिल्कुल एक ही सामान्यीकृत रूप में संकलित होती हैं, इसलिए एक ही निष्पादन योजना निर्मित होती है।