परिचय
एक उत्सुक सूचकांक स्पूल अपने मूल ऑपरेटर को पंक्तियों को वापस करना शुरू करने से पहले, अपने चाइल्ड ऑपरेटर से सभी पंक्तियों को एक अनुक्रमित वर्कटेबल में पढ़ता है। कुछ मामलों में, एक उत्सुक इंडेक्स स्पूल अंतिम अनुपलब्ध अनुक्रमणिका सुझाव . है , लेकिन इसकी रिपोर्ट नहीं की जाती है।
लागत आकलन
अनुक्रमित वर्कटेबल में पंक्तियों को सम्मिलित करना अपेक्षाकृत कम लागत वाला है, लेकिन मुफ़्त नहीं है। ऑप्टिमाइज़र को यह विचार करना चाहिए कि इसमें शामिल कार्य लागत से अधिक बचाता है। इसके लिए स्पूल के पक्ष में काम करने के लिए, स्पूल से पंक्तियों को एक से अधिक बार उपभोग करने के लिए योजना का अनुमान लगाया जाना चाहिए। अन्यथा, यह स्पूल को छोड़ भी सकता है, और केवल एक बार अंतर्निहित ऑपरेशन कर सकता है।
- एक से अधिक बार एक्सेस करने के लिए, स्पूल को नेस्टेड लूप्स जॉइन ऑपरेटर के अंदरूनी हिस्से पर दिखना चाहिए।
- लूप के प्रत्येक पुनरावृत्ति को लूप के बाहरी हिस्से द्वारा प्रदान किए गए एक विशेष इंडेक्स स्पूल कुंजी मान की तलाश करनी चाहिए।
इसका मतलब है कि शामिल होना एक लागू . होना चाहिए , नहीं एक नेस्टेड लूप शामिल हों . दोनों के बीच अंतर के लिए, कृपया मेरा लेख अप्लाई बनाम नेस्टेड लूप्स जॉइन देखें।
उल्लेखनीय विशेषताएं
जबकि एक उत्सुक इंडेक्स स्पूल केवल नेस्टेड लूप के अंदरूनी हिस्से में दिखाई दे सकता है लागू करें , यह "प्रदर्शन स्पूल" नहीं है। एक उत्सुक अनुक्रमणिका स्पूल को ट्रेस फ़्लैग 8690 या NO_PERFORMANCE_SPOOL
के साथ अक्षम नहीं किया जा सकता क्वेरी संकेत।
इंडेक्स स्पूल में डाली गई पंक्तियों को सामान्य रूप से इंडेक्स कुंजी क्रम में पूर्व-सॉर्ट नहीं किया जाता है, जिसके परिणामस्वरूप इंडेक्स पेज स्प्लिट हो सकता है। गैर-दस्तावेजी ट्रेस ध्वज 9260 का उपयोग सॉर्ट करें . उत्पन्न करने के लिए किया जा सकता है इससे बचने के लिए इंडेक्स स्पूल से पहले ऑपरेटर। नकारात्मक पक्ष यह है कि अतिरिक्त छँटाई लागत अनुकूलक को स्पूल विकल्प चुनने से बिल्कुल भी रोक सकती है।
SQL सर्वर किसी b-पेड़ अनुक्रमणिका में समानांतर सम्मिलन का समर्थन नहीं करता है। इसका मतलब है कि समानांतर उत्सुक इंडेक्स स्पूल के नीचे सब कुछ एक ही धागे पर चलता है। स्पूल के नीचे के ऑपरेटर अभी भी (भ्रामक रूप से) समांतरता आइकन के साथ चिह्नित हैं। लिखने . के लिए एक धागा चुना गया है स्पूल को। अन्य सूत्र EXECSYNC
पर प्रतीक्षा करते हैं जबकि यह पूरा होता है। एक बार स्पूल भर जाने के बाद, इसे इससे पढ़ा जा सकता है समानांतर धागों द्वारा।
इंडेक्स स्पूल ऑप्टिमाइज़र को यह नहीं बताते हैं कि वे स्पूल की इंडेक्स कुंजियों द्वारा ऑर्डर किए गए आउटपुट का समर्थन करते हैं। यदि स्पूल से सॉर्ट किया गया आउटपुट आवश्यक है, तो आप एक अनावश्यक सॉर्ट करें . देख सकते हैं ऑपरेटर। वैसे भी उत्सुक इंडेक्स स्पूल को अक्सर एक स्थायी इंडेक्स से बदल दिया जाना चाहिए, इसलिए यह ज्यादातर समय एक छोटी सी चिंता है।
ऐसे पांच अनुकूलक नियम हैं जो एक ईगर इंडेक्स स्पूल generate उत्पन्न कर सकते हैं विकल्प (आंतरिक रूप से इंडेक्स ऑन-द-फ्लाई . के रूप में जाना जाता है ) उत्सुक इंडेक्स स्पूल कहां से आते हैं, यह समझने के लिए हम इनमें से तीन को विस्तार से देखेंगे।
SelToIndexOnTheFly
यह सबसे आम है। यह डेटा-एक्सेस ऑपरेटर के ठीक ऊपर एक या अधिक संबंधपरक चयनों (a.k.a फ़िल्टर या विधेय) से मेल खाता है। SelToIndexOnTheFly
नियम विधेय को एक उत्सुक सूचकांक स्पूल पर खोज विधेय के साथ बदल देता है।
डेमो
एक एडवेंचरवर्क्स नमूना डेटाबेस उदाहरण नीचे दिखाया गया है:
P.ProductID, P.[Name], P.SafetyStockLevel, TH.QuantityFROM उत्पादन का चयन करें। PCROSS के रूप में उत्पाद लागू करें (उत्पादन से MAX(TH.Quantity) चुनें। जहां TH.ProductID =P.ProductID और TH.Quantity
इस निष्पादन योजना की अनुमानित लागत 3.0881 . है इकाइयां रुचि के कुछ बिंदु:
- द नेस्टेड लूप्स इनर जॉइन ऑपरेटर एक लागू है ,
ProductID
. के साथ औरSafetyStockLevel
Product
. से बाहरी संदर्भ . के रूप में तालिका ।- आवेदन के पहले पुनरावृत्ति पर, ईगर इंडेक्स स्पूल क्लस्टर इंडेक्स स्कैन . से पूरी तरह से भरा हुआ है
TransactionHistory
. का टेबल.- स्पूल की वर्कटेबल में एक क्लस्टर इंडेक्स होता है जो
(ProductID, Quantity)
पर होता है। ।- विधियों से मेल खाने वाली पंक्तियाँ
TH.ProductID = P.ProductID
औरTH.Quantity < P.SafetyStockLevel
स्पूल द्वारा इसकी अनुक्रमणिका का उपयोग करके उत्तर दिया जाता है। यह लागू के हर पुनरावृत्ति के लिए सही है, जिसमें पहले वाला भी शामिल है।- द
TransactionHistory
तालिका केवल एक बार स्कैन की जाती है।स्पूल में इनपुट सॉर्ट किया गया
उत्सुक इंडेक्स स्पूल में सॉर्ट किए गए इनपुट को लागू करना संभव है, लेकिन यह अनुमानित लागत को प्रभावित करता है, जैसा कि परिचय में बताया गया है। ऊपर के उदाहरण के लिए, अनिर्दिष्ट ट्रेस फ्लैग को सक्षम करने से स्पूल के बिना एक योजना तैयार होती है:
P.ProductID, P.[Name], P.SafetyStockLevel, TH.QuantityFROM उत्पादन का चयन करें। PCROSS के रूप में उत्पाद लागू करें (उत्पादन से MAX(TH.Quantity) चुनें। जहां TH.ProductID =P.ProductID और TH.Quantity
इस सूचकांक खोज . की अनुमानित लागत और कुंजी लुकअप योजना है 3.11631 इकाइयां यह अकेले इंडेक्स स्पूल वाले प्लान की लागत से अधिक है, लेकिन इंडेक्स स्पूल और सॉर्ट किए गए इनपुट वाले प्लान से कम है।
स्पूल में सॉर्ट किए गए इनपुट के साथ एक योजना देखने के लिए, हमें लूप पुनरावृत्तियों की अपेक्षित संख्या बढ़ाने की आवश्यकता है। यह स्पूल को सॉर्ट करें . की अतिरिक्त लागत चुकाने का मौका देता है .
Product
. से अपेक्षित पंक्तियों की संख्या बढ़ाने का एक तरीका तालिकाName
. बनाना है विधेय कम प्रतिबंधात्मक:P.ProductID, P.[Name], P.SafetyStockLevel, TH.QuantityFROM उत्पादन का चयन करें। PCROSS के रूप में उत्पाद लागू करें (उत्पादन से MAX(TH.Quantity) चुनें। जहां TH.ProductID =P.ProductID और TH.Quantityयह हमें स्पूल में क्रमबद्ध इनपुट के साथ एक निष्पादन योजना देता है:
JoinToIndexOnTheFly
यह नियम आंतरिक जुड़ाव . को रूपांतरित करता है एक लागू करने के लिए , अंदर की तरफ एक उत्सुक इंडेक्स स्पूल के साथ। इस नियम के मिलान के लिए कम से कम एक जॉइन विधेय में असमानता होनी चाहिए।
यह
SelToIndexOnTheFly
. से कहीं अधिक विशिष्ट नियम है , लेकिन विचार बहुत समान है। इस मामले में, चयन (विधेय) को एक इंडेक्स स्पूल सीक में परिवर्तित किया जा रहा है जो कि शामिल होने के साथ जुड़ा हुआ है। शामिल होने से लागू करें . में परिवर्तन जॉइन प्रेडिकेट को जॉइन से ही अप्लाई के अंदरूनी हिस्से में ले जाने की अनुमति देता है।डेमो
P.ProductID, P.[Name], P.SafetyStockLevel, मात्रा =MAX(TH.Quantity) उत्पादन से चुनें। PJOIN उत्पादन के रूप में उत्पाद। TH ON TH के रूप में TransactionHistory। ProductID =P.ProductID और TH. मात्रा
पहले की तरह, हम स्पूल में सॉर्ट किए गए इनपुट का अनुरोध कर सकते हैं:
P.ProductID, P.[Name], P.SafetyStockLevel, मात्रा =MAX(TH.Quantity) उत्पादन से चुनें। PJOIN उत्पादन के रूप में उत्पाद। TH ON TH के रूप में TransactionHistory। ProductID =P.ProductID और TH. मात्रा
इस बार, छँटाई की अतिरिक्त लागत ने अनुकूलक को एक समानांतर योजना चुनने के लिए प्रोत्साहित किया है।
एक अवांछित दुष्प्रभाव सॉर्ट करें . है ऑपरेटर tempdb . पर फैलता है . छँटाई के लिए उपलब्ध कुल स्मृति अनुदान पर्याप्त है, लेकिन यह समान रूप से समानांतर धागे (हमेशा की तरह) के बीच विभाजित है। जैसा कि परिचय में बताया गया है, SQL सर्वर बी-ट्री इंडेक्स में समानांतर इंसर्ट का समर्थन नहीं करता है, इसलिए उत्सुक इंडेक्स स्पूल के नीचे के ऑपरेटर सिंगल थ्रेड पर चलते हैं। इस सिंगल थ्रेड को केवल मेमोरी ग्रांट का एक अंश मिलता है, इसलिए सॉर्ट करें tempdb . तक फैल जाता है ।
यह दुष्प्रभाव शायद एक कारण है कि ट्रेस ध्वज अनिर्दिष्ट और असमर्थित है।
SelSTVFToIdxOnFly
यह नियम वही काम करता है जो
SelToIndexOnTheFly
. करता है , लेकिन एक स्ट्रीमिंग तालिका-मूल्यवान फ़ंक्शन . के लिए (sTVF) पंक्ति स्रोत। डीएमवी और डीएमएफ को अन्य चीजों के साथ लागू करने के लिए इन एसटीवीएफ का आंतरिक रूप से व्यापक रूप से उपयोग किया जाता है। वे आधुनिक निष्पादन योजनाओं में टेबल वैल्यूड फंक्शन . के रूप में दिखाई देते हैं ऑपरेटर (मूल रूप से रिमोट टेबल स्कैन . के रूप में) )।अतीत में, इनमें से कई sTVF एक लागू करें से सहसंबद्ध पैरामीटर स्वीकार नहीं कर सकते थे। वे शाब्दिक, चर और मॉड्यूल पैरामीटर स्वीकार कर सकते थे, बस लागू नहीं बाहरी संदर्भ। दस्तावेज़ीकरण में इसके बारे में अभी भी चेतावनियाँ हैं, लेकिन वे अब कुछ हद तक पुरानी हैं।
वैसे भी, मुद्दा यह है कि कभी-कभी SQL सर्वर के लिए लागू . पास करना संभव नहीं होता है एक sTVF के पैरामीटर के रूप में बाहरी संदर्भ। उस स्थिति में, एसटीवीएफ परिणाम के हिस्से को एक उत्सुक इंडेक्स स्पूल में अमल में लाना समझ में आता है। वर्तमान नियम वह क्षमता प्रदान करता है।
डेमो
अगला कोड उदाहरण एक DMV क्वेरी दिखाता है जो सफलतापूर्वक एक जॉइन से एक लागू . में परिवर्तित हो जाती है . बाहरी संदर्भ दूसरे DMV के पैरामीटर के रूप में पास किए जाते हैं:
-- लागू करने के लिए परिवर्तित-- बाहरी संदर्भ एक पैरामीटर के रूप में पारित चयन DES.session_id, DES.login_time, DESWS.waiting_tasks_countFROM sys.dm_exec_sessions DESJOIN sys.dm_exec_session_wait_stats के रूप में DESWS पर DESWS.session_id =DESWS.session_id के रूप में =DESWS.session_id;
प्रतीक्षा आँकड़े TVF की योजना गुण इनपुट पैरामीटर दिखाते हैं। दूसरा पैरामीटर मान बाहरी संदर्भ . के रूप में प्रदान किया जाता है सत्रों . से डीएमवी:
यह शर्म की बात है कि
sys.dm_exec_session_wait_stats
एक दृश्य है, फ़ंक्शन नहीं, क्योंकि यह हमें लागू करें . लिखने से रोकता है सीधे।आंतरिक रूपांतरण को हराने के लिए नीचे दिया गया पुनर्लेखन पर्याप्त है:
-- TVF पैरामीटर ट्रिकरी से बचने के लिए फिर से लिखें DES.session_id, DES.login_time, DESWS.waiting_tasks_countFROM sys.dm_exec_sessions से DESJOIN sys.dm_exec_session_wait_stats AS DESWS ON DESWS.session_id>=DESWS.session_id पर DESWS.session_id <=DES. (बल आदेश);
session_id
. के साथ विधेय अब पैरामीटर के रूप में उपभोग नहीं किया गया है,SelSTVFToIdxOnFly
नियम उन्हें एक उत्सुक इंडेक्स स्पूल में बदलने के लिए स्वतंत्र है:
मैं आपको इस धारणा के साथ नहीं छोड़ना चाहता कि डीएमवी स्रोत पर एक उत्सुक इंडेक्स स्पूल प्राप्त करने के लिए मुश्किल पुनर्लेखन की आवश्यकता है - यह सिर्फ एक आसान डेमो बनाता है। यदि आप DMV जॉइन के साथ एक प्रश्न का सामना करते हैं जो एक उत्सुक स्पूल के साथ एक योजना तैयार करता है, तो कम से कम आप जानते हैं कि यह वहां कैसे पहुंचा।
आप DMV पर इंडेक्स नहीं बना सकते हैं, इसलिए यदि निष्पादन योजना पर्याप्त रूप से अच्छा प्रदर्शन नहीं करती है, तो आपको हैश या मर्ज जॉइन का उपयोग करने की आवश्यकता हो सकती है।
पुनरावर्ती CTEs
शेष दो नियम हैं
SelIterToIdxOnFly
औरJoinIterToIdxOnFly
. वेSelToIndexOnTheFly
. के सीधे समकक्ष हैं औरJoinToIndexOnTheFly
पुनरावर्ती CTE डेटा स्रोतों के लिए। ये मेरे अनुभव में अत्यंत दुर्लभ हैं, इसलिए मैं इनके लिए डेमो प्रदान नहीं करने जा रहा हूं। (बस इतना हीIter
नियम नाम का हिस्सा समझ में आता है:यह इस तथ्य से आता है कि SQL सर्वर नेस्टेड पुनरावृत्ति के रूप में टेल रिकर्सन को लागू करता है।)जब एक पुनरावर्ती सीटीई को एक आवेदन के अंदर कई बार संदर्भित किया जाता है, तो एक अलग नियम (
SpoolOnIterator
) सीटीई के परिणाम को कैश कर सकता है:R AS के साथ (चुनें 1 AS n UNION सभी चुनें R.n + 1 R से जहां R.n <10) R1 चुनें।निष्पादन योजना में एक दुर्लभ ईजर रो काउंट स्पूल है :
अंतिम विचार
उत्सुक सूचकांक स्पूल अक्सर एक संकेत है कि डेटाबेस स्कीमा से एक उपयोगी स्थायी सूचकांक गायब है। यह हमेशा ऐसा नहीं होता है, जैसा कि स्ट्रीमिंग टेबल-मूल्यवान फ़ंक्शन उदाहरण दिखाते हैं।