SQL को एक घोषणात्मक भाषा के रूप में डिज़ाइन किया गया था, न कि एक प्रक्रियात्मक भाषा के रूप में। तो क्वेरी अनुकूलक को नहीं . होना चाहिए जहां क्लॉज उन्हें लागू करने का निर्धारण करने में भविष्यवाणी करता है, उसके क्रम पर विचार करें।
मैं शायद SQL क्वेरी ऑप्टिमाइज़र की निम्नलिखित चर्चा को अधिक सरल बनाने जा रहा हूँ। मैंने एक साल पहले इन पंक्तियों के साथ लिखा था (यह बहुत मजेदार था!) यदि आप वास्तव में आधुनिक क्वेरी अनुकूलन में खुदाई करना चाहते हैं, तो डैन टो का SQL ट्यूनिंग , ओ'रेली से।
एक साधारण SQL क्वेरी अनुकूलक में, SQL कथन पहले संबंधपरक बीजगणित के ट्री में संकलित हो जाता है संचालन। ये ऑपरेशन प्रत्येक इनपुट के रूप में एक या एक से अधिक टेबल लेते हैं और आउटपुट के रूप में एक और टेबल तैयार करते हैं। स्कैन करें एक अनुक्रमिक स्कैन है जो डेटाबेस से एक तालिका को पढ़ता है। क्रमबद्ध करें एक क्रमबद्ध तालिका उत्पन्न करता है। चुनें एक तालिका बनाता है जिसकी पंक्तियों को कुछ चयन शर्त के अनुसार दूसरी तालिका से चुना जाता है। परियोजना किसी अन्य तालिका के केवल कुछ स्तंभों के साथ एक तालिका उत्पन्न करता है। क्रॉस प्रोडक्ट दो टेबल लेता है और उनकी पंक्तियों की हर कल्पनीय जोड़ी से बना एक आउटपुट टेबल तैयार करता है।
भ्रामक रूप से, SQL SELECT क्लॉज़ को एक रिलेशनल बीजगणित प्रोजेक्ट . में संकलित किया गया है , जबकि WHERE खंड एक संबंधपरक बीजगणित में बदल जाता है चुनें . FROM क्लॉज एक या अधिक जॉइन . में बदल जाता है , प्रत्येक दो टेबल अंदर ले रहा है और एक टेबल बाहर बना रहा है। सेट मिलन, प्रतिच्छेदन, अंतर और सदस्यता से जुड़े अन्य संबंधपरक बीजगणित संचालन हैं, लेकिन इसे सरल रखें।
इस पेड़ को वास्तव में अनुकूलित करने की जरूरत है। उदाहरण के लिए, यदि आपके पास:
select E.name, D.name
from Employee E, Department D
where E.id = 123456 and E.dept_id = D.dept_id
500 विभागों में 5,000 कर्मचारियों के साथ, एक गैर-अनुकूलित पेड़ को क्रियान्वित करने से एक कर्मचारी और एक विभाग (एक क्रॉस उत्पाद) के सभी संभावित संयोजनों को आँख बंद करके तैयार किया जाएगा। ) और फिर चुनें सिर्फ एक संयोजन की जरूरत थी। स्कैन कर्मचारी 5,000 रिकॉर्ड तालिका तैयार करेगा, स्कैन विभाग एक 500 रिकॉर्ड तालिका तैयार करेगा, क्रॉस उत्पाद उन दो तालिकाओं में से 2,500,000 रिकॉर्ड तालिका तैयार होगी, और चुनें E.id पर वह 2,500,000 रिकॉर्ड टेबल लेगा और एक को छोड़कर सभी को छोड़ देगा, वह रिकॉर्ड जो वांछित था।
[असली क्वेरी प्रोसेसर निश्चित रूप से इन सभी इंटरमीडिएट टेबल को याद रखने की कोशिश नहीं करेंगे।]
तो क्वेरी ऑप्टिमाइज़र पेड़ पर चलता है और विभिन्न अनुकूलन लागू करता है। प्रत्येक को अलग करना है चुनें चयन . की श्रृंखला में , प्रत्येक मूल के लिए एक चुनें की शीर्ष स्तर की स्थितियां, वाले और एड एक साथ। (इसे "संयोजक सामान्य रूप" कहा जाता है।) फिर व्यक्ति छोटा चयन करता है पेड़ में चारों ओर ले जाया जाता है और अधिक कुशल बनाने के लिए अन्य संबंधपरक बीजगणित संचालन के साथ विलय कर दिया जाता है।
उपरोक्त उदाहरण में, अनुकूलक पहले चुनें . को धक्का देता है E.id पर =123456 महंगे क्रॉस प्रोडक्ट . से नीचे कार्यवाही। इसका मतलब है क्रॉस प्रोडक्ट सिर्फ 500 पंक्तियों का उत्पादन करता है (उस कर्मचारी और एक विभाग के प्रत्येक संयोजन के लिए एक)। फिर शीर्ष स्तर चुनें E.dept_id =D.dept_id के लिए 499 अवांछित पंक्तियों को फ़िल्टर करता है। बुरा नहीं है।
यदि कर्मचारी के आईडी फ़ील्ड पर कोई अनुक्रमणिका है, तो अनुकूलक स्कैन को जोड़ सकता है चुनें . के साथ कर्मचारी का E.id =123456 पर एक तेज़ अनुक्रमणिका बनाने के लिए लुकअप . इसका मतलब है कि 5,000 के बजाय डिस्क से केवल एक कर्मचारी पंक्ति को मेमोरी में पढ़ा जाता है। चीजें ऊपर दिख रही हैं।
अंतिम प्रमुख अनुकूलन चुनें . लेना है E.dept_id =D.dept_id पर और इसे क्रॉस प्रोडक्ट के साथ मिलाएं . यह इसे एक संबंधपरक बीजगणित में बदल देता है इक्विजॉइन कार्यवाही। यह अपने आप में बहुत कुछ नहीं करता है। लेकिन अगर Department.dept_id पर कोई अनुक्रमणिका है, तो निचले स्तर के अनुक्रमिक स्कैन करें इक्विजॉइन . को खिलाने वाले विभाग के बहुत तेज़ इंडेक्स में बदला जा सकता है लुकअप हमारे एक कर्मचारी के विभाग के रिकॉर्ड का।
कम अनुकूलन में प्रोजेक्ट को आगे बढ़ाना शामिल है संचालन नीचे। यदि आपकी क्वेरी के शीर्ष स्तर को केवल E.name और D.name की आवश्यकता है, और शर्तों के लिए E.id, E.dept_id, और D.dept_id की आवश्यकता है, तो स्कैन करें ऑपरेशंस को अन्य सभी कॉलमों के साथ इंटरमीडिएट टेबल बनाने की ज़रूरत नहीं है, जिससे क्वेरी निष्पादन के दौरान जगह की बचत होती है। हमने एक बेहद धीमी क्वेरी को दो इंडेक्स लुकअप में बदल दिया है और बहुत कुछ नहीं।
मूल प्रश्न की ओर अधिक जानकारी प्राप्त करते हुए, मान लें कि आपको मिल गया है:
select E.name
from Employee E
where E.age > 21 and E.state = 'Delaware'
अडॉप्टिमाइज्ड रिलेशनल अलजेब्रा ट्री, जब क्रियान्वित किया जाता है, तो 5,000 कर्मचारियों में स्कैन करेगा और डेलावेयर में 126 लोगों का उत्पादन करेगा, जो 21 वर्ष से अधिक उम्र के हैं। क्वेरी ऑप्टिमाइज़र के पास डेटाबेस में मूल्यों का कुछ मोटा विचार भी है। यह जान सकता है कि ई.स्टेट कॉलम में 14 राज्य हैं जिनमें कंपनी के स्थान हैं, और ई.एज वितरण के बारे में कुछ है। तो सबसे पहले यह देखता है कि कोई फ़ील्ड अनुक्रमित है या नहीं। यदि ई.स्टेट है, तो यह समझ में आता है कि उस इंडेक्स का उपयोग केवल उन कर्मचारियों की छोटी संख्या को चुनने के लिए किया जाता है जो क्वेरी प्रोसेसर संदिग्ध अपने अंतिम गणना किए गए आंकड़ों के आधार पर डेलावेयर में हैं। यदि केवल E.age है, तो संभवतः क्वेरी प्रोसेसर यह निर्णय लेता है कि यह इसके लायक नहीं है, क्योंकि सभी कर्मचारियों में से 96% 22 वर्ष और उससे अधिक उम्र के हैं। इसलिए यदि ई.स्टेट को अनुक्रमित किया जाता है, तो हमारा क्वेरी प्रोसेसर चुनें . को तोड़ देता है और E.state ='डेलावेयर' को स्कैन . के साथ मिला देता है इसे और अधिक कुशल इंडेक्स स्कैन . में बदलने के लिए ।
आइए इस उदाहरण में कहते हैं कि E.state और E.age पर कोई अनुक्रमणिका नहीं है। संयुक्त चुनें कर्मचारी के क्रमिक "स्कैन" के बाद ऑपरेशन होता है। क्या इससे कोई फर्क पड़ता है कि चुनें . में कौन सी स्थिति है पहले किया जाता है? शायद कोई बड़ी बात नहीं है। क्वेरी प्रोसेसर उन्हें SQL कथन में मूल क्रम में छोड़ सकता है, या यह थोड़ा अधिक परिष्कृत हो सकता है और अपेक्षित व्यय को देख सकता है। आँकड़ों से, यह फिर से पता चलेगा कि E.state ='डेलावेयर' स्थिति अधिक चयनात्मक होनी चाहिए, इसलिए यह शर्तों को उलट देगा और पहले ऐसा करेगा, ताकि 5,000 के बजाय केवल 126 E.age> 21 तुलनाएं हों . या यह महसूस हो सकता है कि स्ट्रिंग समानता तुलना पूर्णांक तुलना की तुलना में बहुत अधिक महंगी है और केवल आदेश छोड़ दें।
किसी भी दर पर, यह सब बहुत जटिल है और आपके वाक्य-विन्यास की स्थिति के क्रम से कोई फर्क पड़ने की संभावना नहीं है। मैं इसके बारे में तब तक चिंता नहीं करूंगा जब तक कि आपके पास वास्तविक प्रदर्शन समस्या न हो और आपका डेटाबेस विक्रेता संकेत के रूप में स्थिति आदेश का उपयोग करता हो।