इंडेक्स सीक बनाम इंडेक्स स्कैन


64

धीमी गति से चलने वाली क्वेरी के निष्पादन योजना को देखते हुए और मैंने देखा कि कुछ नोड्स इंडेक्स सीक हैं और उनमें से कुछ इंडेक्स स्कैन हैं।

सूचकांक खोज और सूचकांक स्कैन में क्या अंतर है?

कौन सा बेहतर प्रदर्शन करता है?

SQL एक को दूसरे पर कैसे चुनता है?

मुझे लगता है कि यह 3 प्रश्न हैं, लेकिन मुझे लगता है कि पहले उत्तर देने से दूसरों की व्याख्या होगी।


6
आपके पास उपयोग-सूचकांक-ल्यूक पर एक अच्छा संदर्भ है ।
मैरियन

7
सभी स्कैन खराब नहीं हैं - कभी-कभी यह क्वेरी को संतुष्ट करने का सबसे कुशल तरीका है। यह भी ध्यान दें कि सभी सीक नहीं चाहते हैं - अक्सर वे वास्तव में रेंज स्कैन होते हैं, और यह केवल यह इंगित करता है कि यह रेंज की शुरुआत में कैसे मिला ।
हारून बर्ट्रेंड

@AaronBertrand लेकिन अगर यह रेंज की शुरुआत में मिलता है और इसे पढ़ता है, तो मूल रूप से इसका मतलब है कि आपको डेटा की आवश्यकता है। इसके अलावा, यह सीमा के अंत की तलाश करता है।
जॉर्ज पोलेवॉय

जवाबों:


76

लघु संस्करण: तलाश ज्यादा बेहतर है

कम लघु संस्करण: तलाश आम तौर पर बहुत बेहतर है, लेकिन एक महान कई (उदाहरण के लिए बुरा सहसंबद्ध उप-प्रश्नों के साथ खराब क्वेरी डिजाइन के कारण, या क्योंकि आप कर्सर ऑपरेशन या अन्य लूप में कई प्रश्न बना रहे हैं) एक से भी बदतर हो सकते हैं स्कैन करें, खासकर अगर आपकी क्वेरी प्रभावित तालिका की अधिकांश पंक्तियों से डेटा लौटा सकती है।

यह डेटा परिवार के लिए पूरे परिवार को कवर करने में मदद करता है ताकि प्रदर्शन के निहितार्थ को पूरी तरह से समझ सकें।

तालिका स्कैन: आपकी क्वेरी के लिए प्रासंगिक सभी अनुक्रमित न होने के साथ, योजनाकार को टेबल स्कैन अर्थ का उपयोग करने के लिए मजबूर किया जाता है जिसका अर्थ है कि प्रत्येक पंक्ति को देखा जाता है। यह तालिका के डेटा से संबंधित हर पृष्ठ पर डिस्क से पढ़ा जा सकता है जो अक्सर सबसे खराब स्थिति होती है। ध्यान दें कि कुछ प्रश्नों के लिए यह तब भी एक टेबल स्कैन का उपयोग करेगा, जब एक उपयोगी सूचकांक मौजूद होता है - यह आमतौर पर होता है क्योंकि तालिका में डेटा इतना छोटा होता है कि यह अनुक्रमणिका को पार करने के लिए अधिक परेशानी वाला होता है (यदि यह मामला है तो आप अपेक्षा करेंगे) जैसे-जैसे डेटा बढ़ता है, इंडेक्स की चयनात्मकता मापता है, बदलने की योजना)।

इंडेक्स स्कैन्स विथ रो लुकअप: इंडेक्स विथ नो इंडेक्स जिसका उपयोग सीधे खोजा जा सकता है के लिए किया जाता है, लेकिन सही कॉलम वाले इंडेक्स में मौजूद इंडेक्स स्कैन का उपयोग किया जा सकता है। उदाहरण के लिए, यदि आपके पास कॉलम 1, कॉल 2, कॉल 3 पर एक सूचकांक के साथ 20 स्तंभों के साथ एक बड़ी तालिका है और आप जारी करते हैं SELECT col4 FROM exampletable WHERE col2=616, तो इस मामले में सूचकांक को क्वेरी col2पर स्कैन करना पूरी तालिका को स्कैन करने से बेहतर है। एक बार जब मिलान पंक्तियाँ मिल जाती हैं, तो डेटा पृष्ठों को आउटपुट (या आगे जुड़ने) के लिए पिकअप कॉल 4 में पढ़ने की आवश्यकता होती है, जो कि "बुकमार्क लुकअप" चरण है जब आप इसे क्वेरी योजनाओं में देखते हैं।

सूचकांक लुकअप के बिना सूचकांक स्कैन: यदि उपरोक्त उदाहरण था SELECT col1, col2, col3 FROM exampletable WHERE col2=616तो डेटा पृष्ठों को पढ़ने के लिए अतिरिक्त प्रयास की आवश्यकता नहीं है: एक बार सूचकांक पंक्तियों के मिलान के बाद col2=616सभी अनुरोधित डेटा ज्ञात हो जाते हैं। यही कारण है कि आप कभी-कभी ऐसे कॉलम देखते हैं जिन्हें कभी खोजा नहीं जाएगा, लेकिन आउटपुट के लिए अनुरोध किए जाने की संभावना है, इंडेक्स के अंत में जोड़ा गया - यह पंक्ति लुकअप को बचा सकता है। इस कारण और केवल इस कारण से एक इंडेक्स में कॉलम जोड़ते समय, उन्हें INCLUDEयह बताने के लिए कि यह कॉलम के आधार पर क्वेरी के लिए इंडेक्स लेआउट को ऑप्टिमाइज़ करने की आवश्यकता नहीं है (यह उन कॉलम में किए गए अपडेट को गति दे सकता है) । इंडेक्स स्कैन बिना किसी फ़िल्टरिंग क्लॉज़ वाले प्रश्नों से हो सकता है: SELECT col2 FROM exampletableटेबल पृष्ठों के बजाय इस उदाहरण इंडेक्स को स्कैन करेगा।

अनुक्रमणिका खोज (पंक्ति लुकअप के साथ या उसके बिना) : एक तलाश में सूचकांक के सभी नहीं माना जाता है। क्वेरी के SELECT * FROM exampletable WHERE c1 BETWEEN 1234 AND 4567लिए क्वेरी इंजन पहली पंक्ति को खोज सकता है जो सूचकांक पर एक पेड़-आधारित खोज करके मेल खाएगा, c1तब तक यह सूचकांक को क्रम में नेविगेट कर सकता है जब तक कि यह सीमा के अंत तक न हो (यह एक क्वेरी के साथ ऐसा ही है के c1=1234रूप में वहाँ कई पंक्तियों के लिए एक =ऑपरेशन के लिए भी स्थिति से मेल खाता हो सकता है )। इसका मतलब यह है कि केवल प्रासंगिक सूचकांक पृष्ठों (प्रारंभिक खोज के लिए कुछ आवश्यक) को सूचकांक (या तालिका) में प्रत्येक पृष्ठ के बजाय पढ़ने की आवश्यकता है।

क्लस्टर्ड इंडेक्स: एक क्लस्टर इंडेक्स के साथ टेबल डेटा को एक अलग हीप स्ट्रक्चर में होने के बजाय उस इंडेक्स के लीफ नोड्स में स्टोर किया जाता है। इसका मतलब यह है कि उस सूचकांक का उपयोग करके पंक्तियों को खोजने के बाद कभी भी कोई अतिरिक्त पंक्ति लुकअप होने की आवश्यकता नहीं होगी, चाहे स्तंभों की आवश्यकता हो [जब तक आपके पास ऑफ-पेज डेटा जैसे TEXTस्तंभ या VARCHAR(MAX)स्तंभ लंबा डेटा न हो]।

इस कारण से आपके पास केवल एक क्लस्टर इंडेक्स हो सकता है [1] , एक अलग ढेर संरचना होने के बजाय क्लस्टर इंडेक्स आपकी तालिका है, इसलिए यदि आप अधिकतम लाभ प्राप्त करने के लिए एक [2] का उपयोग करते हैं, जहां आपने इसे सावधानी से रखा है।

यह भी ध्यान दें कि तालिका के लिए "क्लस्टरिंग कुंजी" के कारण क्लस्टर इंडेक्स और टेबल पर प्रत्येक गैर-क्लस्टर इंडेक्स में शामिल है, इसलिए एक विस्तृत क्लस्टर इंडेक्स आमतौर पर एक अच्छा विचार नहीं है।

[१] वास्तव में, आप प्रभावी रूप से गैर-संकुलित अनुक्रमित को परिभाषित करके कई क्लस्टर अनुक्रमित कर सकते हैं जो तालिका के प्रत्येक स्तंभ को कवर या शामिल करते हैं, लेकिन इससे अंतरिक्ष की बर्बादी होने की संभावना है, लेखन प्रदर्शन प्रभाव पड़ता है इसलिए यदि आप इसे सुनिश्चित करने पर विचार करते हैं तुम सच में की जरूरत है

[२] जब मैं कहता हूं "यदि आप एक क्लस्टर इंडेक्स का उपयोग करते हैं", तो ध्यान दें कि आमतौर पर यह सिफारिश की जाती है कि आपके पास प्रत्येक टेबल पर एक है। सभी नियमों के साथ अपवाद हैं, तालिकाएँ जो थोक आवेषण और अनअॉर्डर रीड्स (ईटीएल प्रक्रियाओं के लिए स्टैगिंग टेबल) के अलावा सबसे आम काउंटर उदाहरण के रूप में बहुत कम देखते हैं।

अतिरिक्त बिंदु: अपूर्ण स्कैन:

यह याद रखना महत्वपूर्ण है कि क्वेरी के बाकी हिस्सों के आधार पर एक टेबल / इंडेक्स स्कैन वास्तव में पूरे टेबल को स्कैन नहीं कर सकता है - यदि तर्क की अनुमति देता है तो क्वेरी प्लान इसे जल्दी से गर्भपात करने में सक्षम हो सकता है। इसका सबसे सरल उदाहरण है SELECT TOP(1) * FROM HugeTable- यदि आप इसके लिए क्वेरी योजना को देखते हैं, तो आप देखेंगे कि स्कैन से केवल एक पंक्ति लौटा दी गई थी और यदि आप IO आँकड़े SET STATISTICS IO ON; SELECT TOP(1) * FROM HugeTableदेखते हैं ( ) तो आप देखेंगे कि यह केवल एक बहुत छोटी संख्या को पढ़ता है पृष्ठों की (शायद सिर्फ एक)।

ऐसा ही हो सकता है यदि एक WHEREया JOIN ... ONक्लॉज़ का विधेय स्कैन के साथ समवर्ती रूप से चलाया जा सकता है जो कि स्रोत है यदि उसका डेटा। क्वेरी प्लानर / रनर कभी-कभी इस तरह से स्कैन को जल्दी समाप्त करने की अनुमति देने के लिए डेटा स्रोतों की ओर आगे बढ़ने पर जोर देने के बारे में बहुत चालाक हो सकता है (और कभी-कभी आप ऐसा करने में मदद करने के लिए प्रश्नों को पुन: व्यवस्थित करने में चतुर हो सकते हैं!)। हालांकि डेटा मानक क्वेरी योजना प्रदर्शन में तीर के अनुसार दाएं-से-बाएं प्रवाहित होता है, तर्क बाएं से दाएं चलता है और अगला शुरू होने से पहले पूरा करने के लिए प्रत्येक चरण (दाएं-से-बाएं) जरूरी नहीं है। यदि आप एक एजेंट के रूप क्वेरी योजना में प्रत्येक ब्लॉक को देखो ऊपर सरल उदाहरण में SELECTएजेंट पूछता है TOPएक पंक्ति है जो बदले में पूछता है के लिए एजेंटTABLE SCANएक के लिए एजेंट, फिर SELECTएजेंट दूसरे के लिए पूछता है, लेकिन TOPएजेंट जानता है कि कोई ज़रूरत नहीं है टेबल रीडर से भी पूछने की जहमत नहीं उठती है, SELECTएजेंट को "कोई और अधिक प्रासंगिक" प्रतिक्रिया नहीं मिलती है और जानता है कि सभी काम पूरा हो गया है। कई ऑपरेशन इस तरह के अनुकूलन को रोकते हैं, इसलिए अक्सर अधिक जटिल उदाहरणों में एक तालिका / सूचकांक स्कैन वास्तव में हर पंक्ति को पढ़ता है, लेकिन इस निष्कर्ष पर कूदने के लिए सावधान रहें कि कोई भी स्कैन एक महंगा ऑपरेशन होना चाहिए।


6

आम तौर पर, कांटे अच्छे होते हैं, स्कैन खराब होते हैं।

सीक उस जगह हैं जहां क्वेरी इंडेक्स का प्रभावी उपयोग करने में सक्षम है, और इसे उन पंक्तियों को खोजने के लिए उपयोग करें जिनकी इसे आवश्यकता है।

स्कैन वह जगह है जहां क्वेरी पूरे सूचकांक के माध्यम से देख रही है कि उसे क्या चाहिए।

SQL कैसे चुनता है? क्वेरी ऑप्टिमाइज़र के इंटर्नल्स में गहरी, निर्णय आपकी क्वेरी और उपलब्ध अनुक्रमित और उन इंडेक्स से जुड़े सांख्यिकीय जानकारी के आधार पर किया जाता है।

पढ़ने के लिए कुछ किताबें हैं जो यहाँ रूचि की हो सकती हैं - दोनों Red-Gate बुकस्टोर से http://www.red-gate.com/community/books/ पर

  • एसक्यूएल सर्वर एक्ज़ीक्यूशन प्लान ग्रांट फ्रिटची ​​द्वारा
  • बेंजामिन नेवरेज द्वारा क्वेरी ऑप्टिमाइज़र के अंदर
  • SQL सर्वर सांख्यिकी Holger Schmeling द्वारा

7
एक ही योजना के लिए एक सिंगल टेबल स्कैन अच्छा है, एक मिलियन सीक्स खराब है। इसलिए आपका पहला कथन पूरी तरह से सही नहीं है।
मैरियन

वास्तव में, इंडेक्स सीक और इंडेक्स स्कैन में प्रत्येक का अपना उपयोग होता है, आप यह नहीं कह सकते कि अंतर्निहित तालिकाओं और प्रश्नों के संदर्भ के बिना एक दूसरे से बेहतर है। अधिकांश समय, यदि किसी तालिका में इसके आंकड़े गलत होते हैं, तो निष्पादन योजना उप-इष्टतम के रूप में सामने आ सकती है, जैसे कि सूचकांक की तलाश गलती से सूचकांक स्कैन और इसके विपरीत चुना जाता है।
जॉयो

5

यदि आप इस विषय को खोदना चाहते हैं, तो एक बहुत ही उपयोगी पुस्तक (कम से कम मेरे लिए) एसक्यूएल सर्वर एक्ज़ीक्यूशन प्लान है जो ग्रांट फ्रिट्ची द्वारा, यहां रेडगेट पर स्वतंत्र रूप से उपलब्ध है

अगर आपके पास कोई क्वेरी है जैसे

SELECT *
FROM myTable

SQL सर्वर संभवतः एक इंडेक्स स्कैन का उपयोग करेगा, क्योंकि आवश्यक परिणामों को प्रदर्शित करने के लिए इसे सभी पंक्तियों से गुजरना होगा।

इसके विपरीत,

SELECT *
FROM myTable
WHERE myID = 1

निश्चित रूप से एक सूचकांक की तलाश में परिणाम होगा। SQL सर्वर myID इंडेक्स की B- ट्री संरचना का उपयोग करेगा और उचित लाइन को पुनः प्राप्त करना बहुत तेज होगा।


मुझे नहीं पता कि मैं "निश्चित रूप से" सहमत हूं - भले ही एक सूचकांक में एक अग्रणी स्तंभ के रूप में myID हो, एक खोज इष्टतम उत्तर नहीं हो सकती है (बहुत सारी चीजों पर निर्भर करती है, जैसे कि यह अद्वितीय है - जो हो सकता है ग्राहकों की तालिका में सही लेकिन ऑर्डर तालिका में ग्राहक के लिए नहीं, कितने कॉलम को कवर करने की आवश्यकता है लेकिन सूचकांक में नहीं हैं, आदि)।
हारून बर्ट्रेंड

मुझे नहीं लगता कि यह जवाब वास्तव में सामने आए सवालों को कवर करता है।
जीरो 3

5

दूसरों ने तलाश और स्कैन के बीच के अंतर को अच्छी तरह से परिभाषित किया है। इस उदाहरण में, आपकी क्वेरी स्वयं और निष्पादन नियोजक को आपको वह जानकारी देनी चाहिए, जिसे आपको यह देखने की आवश्यकता है कि प्रत्येक भाग में क्वेरी के लिए कौन से मूल्य विधेयकों (फ़िल्टर) के रूप में उपयोग किए जाते हैं। आमतौर पर यह विदेशी कुंजियों पर गैर-क्लस्टर इंडेक्स को जोड़ने के लिए एक अच्छा अभ्यास है, और प्रोग्राम कोड में उपयोग के मामलों के आधार पर, आप अतिरिक्त मल्टी-कॉलम इंडेक्स या शामिल कॉलम इंडेक्स भी बनाना चाह सकते हैं। यहां प्रस्तुत शब्दावली के साथ, एक Google खोज प्रत्येक पर उदाहरणों पर अच्छे परिणाम देगा।

लेकिन एक उदाहरण के रूप में, मान लें कि आपका कोड दिए गए फ़िल्टर पर कॉलम A और कॉलम B के लिए क्वेरी कर रहा है, लेकिन आप कॉलम C और कॉलम E के मूल्यों को भी वापस करना चाहते हैं, आप INCLUDE के साथ कॉलम A और B पर एक इंडेक्स बनाना चाहते हैं। कॉलम सी और ई वाले विकल्प, इस तरह से एक एकल इंडेक्स की तलाश में आपकी ज़रूरत की हर चीज़ वापस आ जाएगी, क्योंकि एक ही पंक्ति में अन्य मूल्यों (सी और ई) को पुनः प्राप्त करने के लिए कोई लुकअप करने की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.