अतिथि लेखक:बर्ट वैगनर (@bertwagner)
जॉइन एलिमिनेशन कई तकनीकों में से एक है जो SQL सर्वर क्वेरी ऑप्टिमाइज़र कुशल क्वेरी प्लान बनाने के लिए उपयोग करता है। विशेष रूप से, जॉइन एलिमिनेशन तब होता है जब SQL सर्वर अनावश्यक जॉइन को खत्म करने के लिए क्वेरी लॉजिक या विश्वसनीय डेटाबेस बाधाओं का उपयोग करके समानता स्थापित कर सकता है। मेरे YouTube चैनल पर इस पोस्ट का पूरा वीडियो संस्करण देखें।
एलिमिनेशन इन एक्शन में शामिल हों
जॉइन एलिमिनेशन को समझाने का सबसे सरल तरीका डेमो की एक श्रृंखला है। इन उदाहरणों के लिए मैं WideWorldImporters डेमो डेटाबेस का उपयोग करूँगा।
चीजों को शुरू करने के लिए, हम देखेंगे कि जब एक विदेशी कुंजी मौजूद होती है तो जॉइन एलिमिनेशन कैसे काम करता है:
सेलेक्ट करें।* Sales से।InvoiceLines il INNER JOIN Sales.Invoices i ON il.InvoiceID =i.InvoiceID;
इस उदाहरण में, हम केवल Sales.InvoiceLines से डेटा लौटा रहे हैं, जहां Sales.Invoices में एक मेल खाने वाला InvoiceID पाया जाता है। जबकि आप उम्मीद कर सकते हैं कि निष्पादन योजना Sales.InvoiceLines और Sales.Invoice तालिकाओं पर एक जॉइन ऑपरेटर दिखाने के लिए है, SQL सर्वर कभी भी Sales.Invoices को देखकर परेशान नहीं होता है:
SQL सर्वर Sales.Invoices तालिका में शामिल होने से बचता है क्योंकि यह Sales.InvoiceLines और Sales.Invoices के बीच InvoiceID पर परिभाषित विदेशी कुंजी बाधा द्वारा बनाए गए संदर्भात्मक अखंडता पर भरोसा करता है; यदि Sales.InvoiceLines में कोई पंक्ति मौजूद है, तो InvoiceID के मिलान मान वाली एक पंक्ति होनी चाहिए Sales.Invoices में मौजूद है। और चूंकि हम केवल Sales.InvoiceLines तालिका से डेटा लौटा रहे हैं, SQL सर्वर को Sales.Invoices के किसी भी पृष्ठ को पढ़ने की आवश्यकता नहीं है।
हम सत्यापित कर सकते हैं कि SQL सर्वर बाधा को छोड़कर और हमारी क्वेरी को फिर से चलाकर शामिल होने को समाप्त करने के लिए विदेशी कुंजी बाधा का उपयोग कर रहा है:
वैकल्पिक तालिका [बिक्री]।[चालान] ड्रॉप प्रतिबंध [FK_Sales_InvoiceLines_InvoiceID_Sales_Invoices];
हमारी दो तालिकाओं के बीच संबंध के बारे में कोई जानकारी नहीं होने के कारण, SQL सर्वर को हमारी Sales.Invoices तालिका पर एक अनुक्रमणिका को स्कैन करते हुए, मिलान करने वाले InvoiceIDs को खोजने के लिए एक जॉइन करने के लिए मजबूर किया जाता है।
I/O दृष्टिकोण से, SQL सर्वर को Sales.Invoices तालिका पर एक अनुक्रमणिका से अतिरिक्त 124 पृष्ठ पढ़ना चाहिए, और ऐसा केवल इसलिए है क्योंकि यह एक भिन्न विदेशी कुंजी बाधा द्वारा बनाए गए एक संकीर्ण (एकल स्तंभ) अनुक्रमणिका का उपयोग करने में सक्षम है। यह परिदृश्य बड़ी तालिकाओं या तालिकाओं पर अधिक खराब हो सकता है जो उचित रूप से अनुक्रमित नहीं हैं।
सीमाएं
जबकि पिछला उदाहरण मूल बातें दिखाता है कि कैसे जुड़ना उन्मूलन कार्य करता है, हमें कुछ चेतावनियों से अवगत होने की आवश्यकता है।
सबसे पहले, आइए अपनी विदेशी कुंजी बाधा को वापस जोड़ें:
वैकल्पिक तालिका [बिक्री]।यदि हम अपनी नमूना क्वेरी फिर से चलाते हैं, तो हम देखेंगे कि हमें ऐसी कोई योजना नहीं मिली है जो जॉइन एलिमिनेशन प्रदर्शित करती हो; इसके बजाय हमें एक योजना मिलती है जो हमारे दोनों सम्मिलित तालिकाओं को स्कैन करती है।
ऐसा होने का कारण यह है कि, जब हम अपनी विदेशी कुंजी बाधा को फिर से जोड़ते हैं, तो SQL सर्वर को यह नहीं पता होता है कि इस बीच कोई डेटा संशोधित किया गया है या नहीं। कोई भी नया या बदला हुआ डेटा इस बाधा का पालन नहीं कर सकता है, इसलिए SQL सर्वर हमारे डेटा की वैधता पर भरोसा नहीं कर सकता:
चुनें f.name AS विदेशी_की_नाम, OBJECT_NAME(f.parent_object_id) AS table_name,COL_NAME(fc.parent_object_id, fc.parent_column_id) AS Constraint_column_name ,OBJECT_NAME(f.referenced_object_id),COL_referenced_object_id ,c.referenced_object_id के रूप में। ) as संदर्भित_column_name ,f.is_not_trustedFROM sys.foreign_keys के रूप में f INNER JOIN sys.foreign_key_columns AS fc ON f.object_id =fc.constraint_object_idWHERE f.parent_object_id =OBJECT_ID('Sales.Invoice');
इस बाधा पर SQL सर्वर के भरोसे को फिर से स्थापित करने के लिए, हमें इसकी वैधता की जाँच करनी चाहिए:
वैकल्पिक तालिका [बिक्री]।[चालान लाइन] चेक चेक बाधा के साथ [FK_Sales_InvoiceLines_InvoiceID_Sales_Invoices];बड़ी तालिकाओं पर, इस ऑपरेशन में कुछ समय लग सकता है, SQL सर्वर के ओवरहेड का उल्लेख नहीं करने के लिए इस डेटा को आगे बढ़ने वाले प्रत्येक सम्मिलित/अद्यतन/हटाएं संशोधन के दौरान सत्यापित करना।
एक और सीमा यह है कि SQL सर्वर सम्मिलित तालिकाओं को समाप्त नहीं कर सकता है जब क्वेरी को उन संभावित उन्मूलन उम्मीदवारों से किसी भी डेटा को वापस करने की आवश्यकता होती है:
सिलेक्ट करें*, i.InvoiceDateFROM Sales.InvoiceLines il INNER JOIN Sales.Invoices i ON il.InvoiceID =i.InvoiceID;
उपरोक्त क्वेरी में शामिल होने का उन्मूलन नहीं होता है क्योंकि हम बिक्री से उस डेटा का अनुरोध कर रहे हैं। चालान वापस कर दिए जाते हैं, जिससे SQL सर्वर को उस तालिका से डेटा पढ़ने के लिए मजबूर किया जाता है।
अंत में, यह ध्यान रखना महत्वपूर्ण है कि जब विदेशी कुंजी में कई कॉलम होते हैं, या तालिकाएं tempdb में होती हैं, तो जॉइन एलिमिनेशन नहीं होगा। उत्तरार्द्ध उन कई कारणों में से एक है, जिन्हें आपको अपनी तालिकाओं को tempdb में कॉपी करके अनुकूलन समस्याओं को हल करने का प्रयास नहीं करना चाहिए।
अतिरिक्त परिदृश्य
एकाधिक टेबल
जॉइन एलिमिनेशन केवल दो-टेबल इनर जॉइन और विदेशी कुंजी बाधाओं वाली टेबल तक ही सीमित नहीं है।
उदाहरण के लिए, हम एक अतिरिक्त तालिका बना सकते हैं जो हमारे Sales.Invoices.InvoiceID कॉलम का संदर्भ देती है:
टेबल सेल्स बनाएं।इनवॉइसक्लिकट्रैकिंग (इनवॉइसक्लिकट्रैकिंगआईडी बिगिंट पहचान प्राथमिक कुंजी, चालान आईडी इंट -- अन्य फ़ील्ड यहां जाएंगे); ALTER TABLE [Sales].[InvoiceClickTracking] चेक के साथ CONSTRAINT जोड़ें [FK_Sales_InvoiceClickTracking_InvoiceID_Sales_Invoices] FOREIGN KEY([InvoiceID]) संदर्भ [Sales].[Invoices]); ([InvoiceID]); ([चालान)इस तालिका को हमारी मूल नमूना क्वेरी में शामिल करने से SQL सर्वर भी हमारी Sales.Invoices तालिका को समाप्त कर देगा:
सिलेक्ट il.InvoiceID, ict.InvoiceID from Sales.InvoiceLines il INNER JOIN Sales.Invoices i ON il.InvoiceID =i.InvoiceID INNER JOIN Sales.InvoiceClickTracking ict ON i.InvoiceID =ict.InvoiceID;
SQL सर्वर Sales.Invoices तालिका को समाप्त कर सकता है क्योंकि इन तालिकाओं के संबंधों के बीच संक्रमणीय संबंध हैं।
अद्वितीय बाधाएं
एक विदेशी कुंजी बाधा के बजाय, SQL सर्वर एक अद्वितीय बाधा के साथ डेटा संबंध पर भरोसा कर सकता है, तो वह शामिल उन्मूलन भी करेगा:
वैकल्पिक तालिका [बिक्री]।[चालानक्लिकट्रैकिंग] ड्रॉप प्रतिबंध [FK_Sales_InvoiceClickTracking_InvoiceID_Sales_Invoices]; GO ALTER TABLE Sales.InvoiceClickTracking ADD CONSTRAINT UQ_InvoiceID UNIQUE (InvoiceID); GO SELECT i.InvoiceID from Sales.InvoiceClickTracking ict RIGHT JOIN Sales.Invoices i ON ict.InvoiceID =i.InvoiceID;
बाहरी जुड़ाव
जब तक SQL सर्वर संबंध बाधाओं का अनुमान लगा सकता है, तब तक अन्य प्रकार के जोड़ तालिका उन्मूलन का भी अनुभव कर सकते हैं। उदाहरण के लिए:
सिलेक्ट il.InvoiceIDFROM Sales.InvoiceLines il LEFT JOIN Sales.Invoices i ON il.InvoiceID =i.InvoiceIDचूंकि हमारे पास अभी भी हमारी विदेशी कुंजी बाधा है, जिससे कि Sales.InvoiceLines में प्रत्येक InvoiceID का Sales.Invoices में एक समान InvoiceID होना चाहिए, SQL सर्वर को Sales से सब कुछ वापस करने में कोई समस्या नहीं है। Sales.Invoices में शामिल होने की आवश्यकता के बिना InvoiceLines:
कोई बाधा आवश्यक नहीं
यदि SQL सर्वर गारंटी दे सकता है कि उसे किसी निश्चित तालिका से डेटा की आवश्यकता नहीं होगी, तो यह संभावित रूप से एक जुड़ाव को समाप्त कर सकता है।
इस क्वेरी में कोई जॉइन एलिमिनेशन नहीं होता है क्योंकि SQL सर्वर यह नहीं पहचान सकता है कि Sales.Invoices और Sales.InvoiceLines के बीच संबंध 1-से-1, 1-से-0, या 1-से-अनेक है। यह निर्धारित करने के लिए Sales.InvoiceLines को पढ़ने के लिए मजबूर किया जाता है कि क्या कोई मेल खाने वाली पंक्तियाँ पाई जाती हैं:
चुनें i.InvoiceIDFROM Sales.InvoiceLines il राइट जॉइन सेल्स। इनवॉइस i ON il.InvoiceID =i.InvoiceID;
हालाँकि, यदि हम निर्दिष्ट करते हैं कि हम i.InvoiceIDs का एक DISTINCT सेट चाहते हैं, तो Sales.Invoices से प्रत्येक अद्वितीय मान SQL सर्वर से वापस आता है, भले ही उन पंक्तियों का Sales.InvoiceLines के साथ कोई संबंध हो।
-- सिर्फ यह साबित करने के लिए कि यहां कोई विदेशी कुंजी नहीं चल रही है। वैकल्पिक तालिका [बिक्री]। मैं il.InvoiceID =i.InvoiceID;. पर
दृश्य
जॉइन एलिमिनेशन का एक फायदा यह है कि यह व्यू के साथ काम कर सकता है, भले ही अंतर्निहित व्यू क्वेरी जॉइन एलिमिनेशन का उपयोग करने में सक्षम न हो:
-- हमारी FK ALTER TABLE [बिक्री] वापस जोड़ें। एक क्वेरी का उपयोग करते हुए हमारा विचार जो जॉइन एलिमिनेशन का उपयोग नहीं कर सकता है, बिक्री देखें। vInvoicesAndInvoiceLinesAS चुनें i.InvoiceID, i.InvoiceDate, il.Quantity, il. बिक्री से कर दर। GO -- एलिमिनेशन कार्यों में शामिल हों क्योंकि हम अंतर्निहित Sales.Invoices तालिका से किसी भी कॉलम का चयन नहीं करते हैं, मात्रा का चयन करें, Sales.vInvoicesAndInvoiceLines से कर की दर;
निष्कर्ष
जॉइन एलिमिनेशन एक अनुकूलन है जो SQL सर्वर तब करता है जब यह निर्धारित करता है कि यह सबमिट की गई क्वेरी में निर्दिष्ट सभी तालिकाओं से डेटा पढ़ने की आवश्यकता के बिना एक सटीक परिणाम सेट प्रदान कर सकता है। यह अनुकूलन SQL सर्वर को पढ़ने वाले पृष्ठों की संख्या को कम करके महत्वपूर्ण प्रदर्शन सुधार प्रदान कर सकता है, हालांकि यह अक्सर कुछ डेटाबेस बाधाओं को बनाए रखने की आवश्यकता की कीमत पर आता है। हम उन्मूलन में शामिल होने वाली सरल निष्पादन योजनाओं को प्राप्त करने के लिए प्रश्नों को पुन:सक्रिय कर सकते हैं, हालांकि क्वेरी ऑप्टिमाइज़र को अनावश्यक जुड़ावों को हटाकर हमारी योजनाओं को स्वचालित रूप से सरल बनाना एक अच्छा लाभ है।
फिर से, मैं आपको इस पोस्ट का पूरा वीडियो संस्करण देखने के लिए आमंत्रित करता हूं।
लेखक के बारे में
बर्ट क्लीवलैंड, ओहायो का एक बिजनेस इंटेलिजेंस डेवलपर है। वह तेजी से चलने वाले प्रश्नों को लिखना पसंद करता है और दूसरों को आत्मनिर्भर SQL समस्या समाधानकर्ता बनने में मदद करता है। बर्ट, bertwagner.com पर SQL सर्वर के बारे में ब्लॉग करता है और youtube.com/c/bertwagner पर SQL सर्वर YouTube वीडियो बनाता है।