SQL सर्वर में दो तालिकाओं को एक साथ जोड़ने के लिए उपलब्ध एल्गोरिदम में से एक नेस्टेड लूप्स है। नेस्टेड लूप जॉइन एक जॉइन इनपुट को बाहरी इनपुट टेबल के रूप में और एक को इनर इनपुट टेबल के रूप में उपयोग करता है। बाहरी लूप बाहरी इनपुट तालिका पंक्ति को पंक्ति द्वारा पुनरावृत्त करता है। प्रत्येक बाहरी पंक्ति के लिए निष्पादित आंतरिक लूप, आंतरिक इनपुट तालिका में मिलान वाली पंक्तियों की खोज करता है।
इसे नैव नेस्टेड लूप जॉइन कहा जाता है।
यदि आपके पास आंतरिक इनपुट तालिका में शामिल होने की स्थिति पर एक सूचकांक है, तो बाहरी तालिका की प्रत्येक पंक्ति के लिए एक आंतरिक लूप करना आवश्यक नहीं है। इसके बजाय, आप बाहरी तालिका से मान को खोज तर्क के रूप में पास कर सकते हैं, और आंतरिक तालिका की सभी लौटाई गई पंक्तियों को बाहरी तालिका की पंक्तियों से जोड़ सकते हैं।
आंतरिक तालिका द्वारा खोज एक यादृच्छिक अभिगम है। संस्करण 2005 से शुरू होने वाले SQL सर्वर में बैच सॉर्ट ऑप्टिमाइज़ेशन है (कॉलमस्टोर इंडेक्स के लिए बैच मोड में सॉर्ट ऑपरेटर के साथ भ्रमित न हों)। ऑप्टिमाइज़ेशन का उद्देश्य आंतरिक तालिका से डेटा प्राप्त करने से पहले बाहरी तालिका से खोज कुंजी को ऑर्डर करना है। इस प्रकार, एक यादृच्छिक अभिगम अनुक्रमिक होगा।
निष्पादन योजना एक अलग ऑपरेटर के रूप में बैच सॉर्ट कार्रवाई प्रदर्शित नहीं करता है। इसके बजाय, आप नेस्टेड लूप्स ऑपरेटर में ऑप्टिमाइज़्ड =ट्रू प्रॉपर्टी देख सकते हैं। यदि योजना में बैच सॉर्ट को एक अलग ऑपरेटर के रूप में देखना संभव होता, तो यह निम्न जैसा दिखेगा:
इस छद्म योजना में, हम इस CustomerID अनुक्रमणिका कुंजी के क्रम में गैर-संकुल ix_CustomerID अनुक्रमणिका से डेटा पढ़ते हैं। फिर, हमें क्लस्टर इंडेक्स में की लुकअप करने की आवश्यकता है, क्योंकि ix_CustomerID एक कवरिंग इंडेक्स नहीं है। की लुकअप एक क्लस्टर्ड इंडेक्स की सर्च ऑपरेशन है - एक रैंडम एक्सेस। इसे अनुक्रमिक बनाने के लिए, SQL सर्वर क्लस्टर इंडेक्स कुंजी द्वारा बैच सॉर्ट निष्पादित कर सकता है।
बैच सॉर्ट के बारे में अधिक जानने के लिए, कृपया मेरा लेख बैच सॉर्ट और नेस्टेड लूप्स देखें।
यह अनुकूलन पर्याप्त संख्या में पंक्तियों के साथ एक महान बढ़ावा प्रदान करता है। आप इसके परीक्षण परिणामों के बारे में ब्लॉग ऑप्टिमाइज्ड नेस्टेड लूप्स जॉइन में पढ़ सकते हैं, जिसे क्रेग फ्रीडमैन, एक ऑप्टिमाइज़र डेवलपर द्वारा बनाया गया है।
हालाँकि, यदि पंक्तियों की वास्तविक संख्या अपेक्षा से कम है, तो इस प्रकार के निर्माण के लिए CPU अतिरिक्त लागत इसके लाभों को छिपा सकती है, CPU खपत को बढ़ा सकती है और इसके प्रदर्शन को कम कर सकती है।
इस विशेष उदाहरण पर विचार करें:
use tempdb; go -- create a test table (SalesOrderID - clustered PK) create table dbo.SalesOrder(SalesOrderID int identity primary key, CustomerID int not null, SomeData char(200) not null); go -- add test data with n as (select top(1000000) rn = row_number() over(order by (select null)) from sys.all_columns c1,sys.all_columns c2) insert dbo.SalesOrder(CustomerID, SomeData) select rn%500000, str(rn,100) from n; -- create a clustered index create index ix_c on dbo.Salesorder(CustomerID); go -- the batch sort optimization is enabled by default (Nested Loops: Optimized = true) select * from dbo.SalesOrder with(index(ix_c)) where CustomerID < 1000; -- disable it with the DISABLE_OPTIMIZED_NESTED_LOOP hint (Nested Loops: Optimized = false) select * from dbo.SalesOrder with(index(ix_c)) where CustomerID < 1000 option(use hint('DISABLE_OPTIMIZED_NESTED_LOOP')); go
लौटा हुआ परिणाम:
मैं आपका ध्यान आउटपुट में पंक्तियों के विभिन्न क्रम की ओर आकर्षित करना चाहूंगा। सर्वर पंक्तियों को उसी क्रम में लौटाता है जिस क्रम में यह उन्हें संसाधित करता है क्योंकि हमने स्पष्ट रूप से ORDER BY निर्दिष्ट नहीं किया है। पहले मामले में, हम धीरे-धीरे ix_c इंडेक्स से पढ़ते हैं। हालांकि, संकुल सूचकांक से यादृच्छिक रीडिंग को अनुकूलित करने के लिए, हम संकुल SalesOrderID अनुक्रमणिका कुंजी द्वारा पंक्तियों को फ़िल्टर करते हैं। दूसरे मामले में, कोई प्रकार नहीं है, साथ ही गैर-संकुल सूचकांक ix_c के CustomerID कुंजी क्रम में पढ़ा जाता है।
2340 ट्रेस फ्लैग से अंतर
इस तथ्य के बावजूद कि दस्तावेज़ 2340 ट्रेस ध्वज को DISABLE_OPTIMIZED_NESTED_LOOP संकेत के समकक्ष के रूप में निर्दिष्ट करता है, यह वास्तव में सत्य नहीं है।
निम्नलिखित उदाहरण पर विचार करें जहां मैं अद्यतन आंकड़ों का उपयोग करूंगा ... पेजकाउंट अनिर्दिष्ट कमांड के साथ ऑप्टिमाइज़र को यह कहकर धोखा देने के लिए कि तालिका वास्तव में उससे अधिक पृष्ठ लेती है। फिर, इन प्रश्नों पर एक नज़र डालें:
- बिना किसी संकेत के (मैंने एक साधारण योजना रखने के लिए MAXDOP जोड़ा है);
- DISABLE_OPTIMIZED_NESTED_LOOP संकेत के साथ;
- 2340 ट्रेस फ्लैग के साथ।
-- create a huge table update statistics dbo.SalesOrder with pagecount = 100000; go set showplan_xml on; go -- 1. without hints select * from dbo.SalesOrder with(index(ix_c)) where CustomerID < 1000000 option(maxdop 1); -- 2. hint select * from dbo.SalesOrder with(index(ix_c)) where CustomerID < 1000000 option(use hint('DISABLE_OPTIMIZED_NESTED_LOOP'), maxdop 1); -- 3. trace flag select * from dbo.SalesOrder with(index(ix_c)) where CustomerID < 1000000 option(querytraceon 2340, maxdop 1); go set showplan_xml off; go
परिणामस्वरूप, हमारे पास निम्नलिखित योजनाएँ हैं:
नेस्टेड लूप्स में तीनों योजनाओं में अनुकूलित =झूठी संपत्ति है। तथ्य यह है कि टेबल की चौड़ाई बढ़ाकर, हम डेटा एक्सेस लागत भी बढ़ाते हैं। जब लागत काफी अधिक होती है, तो SQL सर्वर निहित बैच सॉर्ट ऑपरेटर के बजाय स्पष्ट सॉर्ट ऑपरेटर का उपयोग कर सकता है। हम इसे पहली क्वेरी योजना में देख सकते हैं।
दूसरी क्वेरी में, हमने DISABLE_OPTIMIZED_NESTED_LOOP संकेत का उपयोग किया जो निहित बैच सॉर्ट को बंद कर देता है। हालांकि, यह एक अलग ऑपरेटर द्वारा स्पष्ट छँटाई को हटा देता है।
तीसरी योजना में, हम देख सकते हैं कि 2340 ट्रेस फ्लैग जोड़ने के बावजूद, सॉर्ट ऑपरेटर मौजूद है।
इस प्रकार, ध्वज से संकेत का अंतर इस प्रकार है:एक संकेत इस तथ्य पर निर्भर करता है कि सर्वर इसे निहित बैच सॉर्ट के साथ या अलग सॉर्ट ऑपरेटर के साथ लागू करता है या नहीं, इस तथ्य के आधार पर एक यादृच्छिक पहुंच को एक सीरियल में बदलकर अनुकूलन को अक्षम करता है।पी>
पी.एस. योजनाएं उपकरण पर निर्भर हो सकती हैं। इस प्रकार, यदि आप इन प्रश्नों को चलाने में विफल रहते हैं, तो dbo.SalesOrder तालिका विवरण में SomeData char(200) स्तंभ आकार को बढ़ाने या घटाने का प्रयास करें।
लेख का अनुवाद लेखक की अनुमति से Codingsight टीम द्वारा किया गया था।