क्या पहली योजना में स्पूल इटरेटर का कोई प्रशंसनीय लाभ है?
यह इस बात पर निर्भर करता है कि आप "प्रशंसनीय" के रूप में क्या मानते हैं, लेकिन लागत मॉडल के अनुसार उत्तर हां है। बेशक यह सच है, क्योंकि ऑप्टिमाइज़र हमेशा सबसे सस्ती योजना चुनता है जिसे वह पाता है।
असली सवाल यह है कि लागत मॉडल स्पूल के साथ योजना को बिना योजना की तुलना में इतना सस्ता क्यों मानता है। डेल्टा स्टोर में किसी भी पंक्तियों को जोड़ने से पहले एक ताजा तालिका (आपकी स्क्रिप्ट से) के लिए बनाई गई अनुमानित योजनाओं पर विचार करें:
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE);
इस योजना की अनुमानित लागत 771,734 इकाई है :
लागत लगभग सभी क्लस्टर्ड इंडेक्स डिलीट से जुड़ी है, क्योंकि विलोपन के परिणामस्वरूप यादृच्छिक I / O का एक बड़ा सौदा होने की उम्मीद है। यह केवल सामान्य तर्क है जो सभी डेटा संशोधनों पर लागू होता है। उदाहरण के लिए, बी-ट्री इंडेक्स में संशोधनों का एक अनियंत्रित सेट माना जाता है कि एक उच्च I / O लागत के साथ बड़े पैमाने पर यादृच्छिक I / O में परिणाम होता है।
डेटा-बदलने की योजना में क्रमबद्ध रूप से इन पंक्तियों को क्रमबद्ध रूप से प्रस्तुत करने की सुविधा हो सकती है, जो इन लागत कारणों से क्रमिक पहुँच को बढ़ावा देगी। इस मामले में प्रभाव समाप्त हो जाता है क्योंकि तालिका का विभाजन होता है। बहुत विभाजन, वास्तव में; आपकी स्क्रिप्ट उनमें से 15,000 का निर्माण करती है। बहुत विभाजन तालिका में रैंडम अपडेट की विशेष रूप से उच्च लागत होती है क्योंकि विभाजन (पंक्तियों) को मध्य-धारा में बदलने की कीमत के साथ-साथ उच्च लागत भी दी जाती है।
विचार करने के लिए अंतिम प्रमुख कारक यह है कि ऊपर दी गई सरल अद्यतन क्वेरी (जहां 'अपडेट' का अर्थ है किसी भी डेटा-बदलने वाला ऑपरेशन, जिसमें एक डिलीट भी शामिल है) "रूसेट शेयरिंग" नामक एक अनुकूलन के लिए अर्हता प्राप्त करता है, जहां स्कैनिंग और दोनों के लिए एक ही आंतरिक रोसेट का उपयोग किया जाता है। तालिका को अद्यतन करना। निष्पादन योजना अभी भी दो अलग-अलग ऑपरेटरों को दिखाती है, लेकिन फिर भी, केवल एक ही पंक्तियों का उपयोग किया जाता है।
मैं इसका उल्लेख करता हूं क्योंकि इस अनुकूलन को लागू करने में सक्षम होने का मतलब है कि ऑप्टिमाइज़र एक कोड पथ लेता है जो बस यादृच्छिक I / O की लागत को कम करने के लिए स्पष्ट रूप से छंटाई के संभावित लाभों पर विचार नहीं करता है । जहां टेबल एक बी-ट्री है, यह समझ में आता है, क्योंकि संरचना स्वाभाविक रूप से आदेशित होती है, इसलिए पंक्तियों को साझा करने से स्वचालित रूप से सभी संभावित लाभ मिलते हैं।
महत्वपूर्ण परिणाम यह है कि अद्यतन ऑपरेटर के लिए लागत तर्क इस आदेश लाभ (क्रमिक I / O या अन्य अनुकूलन को बढ़ावा देने) पर विचार नहीं करता है जहां अंतर्निहित ऑब्जेक्ट स्तंभ की दुकान है। इसका कारण यह है कि कॉलम स्टोर संशोधनों को इन-प्लेस नहीं किया जाता है; वे एक डेल्टा स्टोर का उपयोग करते हैं। इसलिए लागत मॉडल बी-पेड़ों बनाम कॉलमस्टोर्स पर साझा-पंक्तियों के अपडेट के बीच अंतर को दर्शा रहा है।
फिर भी, एक (बहुत!) विभाजन किए गए स्तंभ की विशेष स्थिति में, संरक्षित ऑर्डर करने के लिए अभी भी एक लाभ हो सकता है, जिसमें एक विभाजन से पहले सभी अपडेट करने से पहले एक I / O के दृष्टिकोण से लाभप्रद हो सकता है ।
यहां कॉलम स्टोर के लिए मानक लागत तर्क का पुन: उपयोग किया जाता है, इसलिए एक योजना जो विभाजन आदेश को संरक्षित करती है (हालांकि प्रत्येक विभाजन के भीतर आदेश नहीं) कम लागत वाली है। अपडेट ऑपरेटर को सॉर्ट किए गए इनपुट की आवश्यकता के लिए हम इसे अनकॉम्लेटेड ट्रेस ध्वज 2332 का उपयोग करके परीक्षण क्वेरी पर देख सकते हैं। यह DMLRequestSort
संपत्ति को अद्यतन करने के लिए सेट करता है , और ऑप्टिमाइज़र को एक योजना बनाने के लिए मजबूर करता है जो अगले विभाजन के लिए जाने से पहले एक विभाजन के लिए सभी पंक्तियाँ प्रदान करता है:
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE, QUERYTRACEON 2332);
इस योजना की अनुमानित लागत बहुत कम है, 52.5174 इकाइयों पर:
लागत में यह कमी अपडेट में कम अनुमानित I / O लागत के कारण है। प्रस्तुत स्पूल कोई उपयोगी कार्य नहीं करता है, सिवाय इसके कि यह विभाजन के क्रम में आउटपुट की गारंटी दे सकता है, जैसा कि अपडेट के लिए आवश्यक है DMLRequestSort = true
(कॉलम स्टोर इंडेक्स का सीरियल स्कैन इस गारंटी को प्रदान नहीं कर सकता है)। स्पूल की लागत को अपेक्षाकृत कम माना जाता है, विशेष रूप से अद्यतन में लागत में (शायद अवास्तविक) कमी के साथ तुलना में।
अद्यतन ऑपरेटर को आदेशित इनपुट की आवश्यकता के बारे में निर्णय क्वेरी अनुकूलन में बहुत जल्दी किया जाता है। इस निर्णय में उपयोग किए गए अनुमानों को कभी भी प्रलेखित नहीं किया गया है, लेकिन परीक्षण और त्रुटि के माध्यम से निर्धारित किया जा सकता है। ऐसा लगता है कि किसी भी डेल्टा स्टोर का आकार इस निर्णय के लिए एक इनपुट है। एक बार बनाने के बाद, विकल्प क्वेरी संकलन के लिए स्थायी है। कोई USE PLAN
संकेत सफल नहीं होगा: योजना के लक्ष्य ने या तो अपडेट के लिए इनपुट का आदेश दिया है, या यह नहीं करता है।
कार्डिनिटी अनुमान को कृत्रिम रूप से सीमित किए बिना इस क्वेरी के लिए कम लागत वाली योजना प्राप्त करने का एक और तरीका है। स्पूल से बचने के लिए पर्याप्त रूप से कम अनुमान संभवतः DMLRequestSort के परिणामस्वरूप गलत होगा, जिसके परिणामस्वरूप अपेक्षित यादृच्छिक I / O के कारण बहुत अधिक अनुमानित योजना लागत होती है। 2332 (DMLRequestSort = true) के साथ संयोजन में ट्रेस ध्वज 8649 (समानांतर योजना) का उपयोग करने के लिए एक विकल्प है:
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE, QUERYTRACEON 2332, QUERYTRACEON 8649);
प्रति-बैच बैच-मोड समानांतर स्कैन और ऑर्डर-प्रोटेक्शन (मर्जिंग) इकट्ठा करने की योजना में यह परिणाम प्राप्त होता है:
आपके हार्डवेयर पर विभाजन आदेश के रन-टाइम प्रभावशीलता के आधार पर, यह तीनों में से सर्वश्रेष्ठ प्रदर्शन कर सकता है। उस ने कहा, बड़े संशोधन कॉलम स्टोर पर एक महान विचार नहीं हैं, इसलिए विभाजन-स्विचिंग विचार लगभग निश्चित रूप से बेहतर है। यदि आप लंबे संकलन समय और विचित्र योजना विकल्पों का सामना कर सकते हैं जो अक्सर विभाजित वस्तुओं के साथ देखा जाता है - खासकर जब विभाजन की संख्या बड़ी हो।
कई, अपेक्षाकृत नई, सुविधाओं को मिलाकर, विशेष रूप से उनकी सीमाओं के पास, खराब निष्पादन योजनाओं को प्राप्त करने का एक शानदार तरीका है। ऑप्टिमाइज़र समर्थन की गहराई समय के साथ बेहतर होती जाती है, लेकिन कॉलम स्टोर के 15,000 विभाजनों का उपयोग करने की संभावना हमेशा दिलचस्प समय में रहती है।
OPTION (QUERYRULEOFF EnforceHPandAccCard)
तो स्पूल गायब हो जाता है। मुझे लगता है कि एचपी "हेलोवीन संरक्षण" हो सकता है। हालाँकि तब एकUSE PLAN
संकेत के साथ उस योजना का उपयोग करने की कोशिश विफल रहती है (जैसा किOPTIMIZE FOR
वर्कअराउंड से भी योजना का उपयोग करने की कोशिश करता है)