MySQL इंडेक्स कैसे काम करते हैं?


402

मुझे वास्तव में दिलचस्पी है कि कैसे MySQL अनुक्रमित काम करते हैं, अधिक विशेष रूप से, वे पूरी तालिका को स्कैन किए बिना अनुरोध किए गए डेटा को कैसे वापस कर सकते हैं?

यह ऑफ-टॉपिक है, मुझे पता है, लेकिन अगर कोई ऐसा व्यक्ति है जो मुझे इस बारे में विस्तार से समझा सकता है, तो मैं बहुत, बहुत आभारी रहूंगा।



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

SELECT * FROM members WHERE id = '1'- तो क्यों सूचकांक के साथ यह तेजी से काम करता है? वह सूचकांक यहाँ क्या करता है?
good_evening 16:25

2
यह एक क्वेरी की तरह दिखता है जो बस एक विशिष्ट, अनुक्रमित रिकॉर्ड (शायद प्राथमिक कुंजी द्वारा पहचाना जाता है) को देखता है। इंडेक्स इसे अधिक तेज़ बनाता है क्योंकि यह मेमोरी में संग्रहीत होता है, संबंधित इंडेक्स पंक्ति को देखा जा सकता है और इसमें एक पॉइंटर होता है जहां वास्तविक डेटा संग्रहीत होता है। इसलिए MySQL तालिका को स्कैन किए बिना तालिका में सटीक स्थान पर जा सकता है।
हैमराइट

बहुत अच्छा धन्यवाद!
ऑर्बिट में लाइटनेस दौड़

जवाबों:


513

मूल रूप से एक मेज पर एक सूचकांक एक पुस्तक में एक सूचकांक की तरह काम करता है (यह वह जगह है जहां से नाम आया है):

मान लीजिए कि आपके पास डेटाबेस के बारे में एक पुस्तक है और आप भंडारण, के बारे में कुछ जानकारी प्राप्त करना चाहते हैं। सूचकांक के बिना (कोई अन्य सहायता नहीं, जैसे कि सामग्री की तालिका) आपको एक-एक करके पृष्ठों के माध्यम से जाना होगा, जब तक कि आपको विषय नहीं मिला (वह है full table scan)। दूसरी ओर, एक सूचकांक में कीवर्ड की एक सूची होती है, इसलिए आप सूचकांक से परामर्श करेंगे और देखेंगे कि storageपृष्ठ 113-120,231 और 354 पर उल्लेख किया गया है। तब आप बिना खोज किए सीधे उन पृष्ठों पर फ्लिप कर सकते हैं (यह एक खोज है सूचकांक, कुछ तेज)।

बेशक, सूचकांक कितना उपयोगी होगा, यह कई बातों पर निर्भर करता है - कुछ उदाहरण, ऊपर दिए गए उपमा का उपयोग करते हुए:

  • यदि आपके पास डेटाबेस पर एक पुस्तक थी और "डेटाबेस" शब्द को अनुक्रमित किया था, तो आप देखेंगे कि इसका उल्लेख पृष्ठों 1-59,61-290 और 292 से 400 पर किया गया है। ऐसे मामले में, सूचकांक ज्यादा मददगार नहीं है और यह हो सकता है एक-एक करके (एक डेटाबेस में, यह "खराब चयनात्मकता") पन्नों के माध्यम से जाने के लिए तेज़ हो।
  • 10-पृष्ठ की पुस्तक के लिए, इंडेक्स बनाने का कोई मतलब नहीं है, जैसा कि आप 5-पेज इंडेक्स द्वारा 10-पेज की किताब के साथ समाप्त कर सकते हैं, जो सिर्फ मूर्खतापूर्ण है - बस 10 पृष्ठों को स्कैन करें और इसके साथ किया जाए ।
  • सूचकांक को भी उपयोगी बनाने की आवश्यकता है - आमतौर पर सूचकांक का कोई मतलब नहीं है उदाहरण के लिए प्रति पृष्ठ पत्र "एल" की आवृत्ति।

3
आप बता रहे हैं कि यह क्या है, न कि तकनीकी रूप से यह आंतरिक रूप से कैसे काम करता है।
टूटू कुमारी

@ टुटु कुमारी: सवाल का संशोधन देखें; वर्तमान प्रश्न को फिट करने के लिए उत्तर को भी बेझिझक पढ़ें (विभिन्न इंजनों और सूचकांक प्रकारों पर ध्यान दें - उदाहरण देखें यहां प्रलेखन: dev.mysql.com/doc/refman/8.0/en/index-btree-hash.html )
पिस्कॉर ने इमारत

259

पहली बात जो आपको पता होनी चाहिए कि अनुक्रमणिका पूर्ण तालिका को स्कैन करने से बचने का एक तरीका है ताकि आप जिस परिणाम की तलाश कर रहे हैं।

विभिन्न प्रकार के अनुक्रमणिका हैं और वे संग्रहण परत में कार्यान्वित किए जाते हैं, इसलिए उनके बीच कोई मानक नहीं है और वे उस संग्रहण इंजन पर भी निर्भर करते हैं जिसका आप उपयोग कर रहे हैं।

InnoDB और B + ट्री इंडेक्स

InnoDB के लिए, सबसे सामान्य सूचकांक प्रकार B + ट्री आधारित सूचकांक है, जो तत्वों को क्रमबद्ध क्रम में संग्रहीत करता है। इसके अलावा, आपको अनुक्रमित मान प्राप्त करने के लिए वास्तविक तालिका तक पहुंचने की आवश्यकता नहीं है, जो आपकी क्वेरी को तेजी से वापस कर देता है।

इस इंडेक्स प्रकार के बारे में "समस्या" यह है कि आपको इंडेक्स का उपयोग करने के लिए सबसे बाईं ओर क्वेरी करनी होगी। इसलिए, यदि आपके सूचकांक में दो कॉलम हैं, तो last_name और first_name कहें, जो आदेश आप इन क्षेत्रों को क्वेरी करते हैं वह बहुत मायने रखता है

तो, निम्न तालिका दी गई है:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

यह क्वेरी सूचकांक का लाभ उठाएगी:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

लेकिन निम्नलिखित एक नहीं होगा

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

क्योंकि आप first_nameपहले कॉलम को क्वेरी कर रहे हैं और यह इंडेक्स में सबसे बाएं कॉलम नहीं है।

यह अंतिम उदाहरण और भी बुरा है:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

क्योंकि अब, आप इंडेक्स में सबसे दाएं क्षेत्र के सबसे दाहिने हिस्से की तुलना कर रहे हैं।

हैश इंडेक्स

यह एक अलग सूचकांक प्रकार है जो दुर्भाग्य से, केवल मेमोरी बैकेंड का समर्थन करता है। यह तेज़ बिजली है, लेकिन केवल पूर्ण लुकअप के लिए उपयोगी है, जिसका अर्थ है कि आप इसका उपयोग परिचालन के लिए नहीं कर सकते हैं >, <या LIKE

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

यदि आपके पास एक बड़ा VARCHARक्षेत्र है, तो आप एक बी-ट्री का उपयोग करके, एक और कॉलम बनाकर और उस पर बड़े मूल्य के एक हैश को बचाकर हैश इंडेक्स के उपयोग का "अनुकरण" कर सकते हैं। मान लीजिए कि आप किसी फ़ील्ड में url स्टोर कर रहे हैं और मान काफी बड़े हैं। आप एक पूर्णांक फ़ील्ड भी बना सकते हैं जिसे कहा जाता है url_hashऔर CRC32इसे सम्मिलित करते समय url को हैश करने के लिए या किसी अन्य हैश फ़ंक्शन जैसे हैश फ़ंक्शन का उपयोग करें। और फिर, जब आपको इस मूल्य के लिए क्वेरी करने की आवश्यकता होती है, तो आप कुछ इस तरह से कर सकते हैं:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

उपरोक्त उदाहरण के साथ समस्या यह है कि चूंकि CRC32फ़ंक्शन एक बहुत छोटा हैश उत्पन्न करता है, आप हैश के मूल्यों में बहुत सारे टकराव के साथ समाप्त करेंगे। यदि आपको सटीक मान चाहिए, तो आप निम्न कार्य करके इस समस्या को ठीक कर सकते हैं:

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

यह अभी भी हैश चीजों के लायक है भले ही टकराव की संख्या अधिक होने के कारण आप केवल दूसरी तुलना (स्ट्रिंग एक) बार-बार हैश के खिलाफ प्रदर्शन करेंगे।

दुर्भाग्य से, इस तकनीक का उपयोग करते हुए, आपको अभी भी urlफ़ील्ड की तुलना करने के लिए तालिका को हिट करने की आवश्यकता है ।

लपेटें

अनुकूलन के बारे में बात करने के लिए कुछ तथ्य जो आप हर बार विचार कर सकते हैं:

  1. स्ट्रिंग तुलना की तुलना में पूर्णांक तुलना तेजी से होती है। यह हैश इंडेक्स के अनुकरण के बारे में उदाहरण के साथ चित्रित किया जा सकता है InnoDB

  2. हो सकता है, एक प्रक्रिया में अतिरिक्त कदम जोड़ने से यह तेज हो, धीमी न हो। यह इस तथ्य से स्पष्ट किया जा सकता है कि आप SELECTइसे दो चरणों में विभाजित करके अनुकूलित कर सकते हैं , जिससे एक नई बनाई गई मेमोरी टेबल में पहले एक स्टोर वैल्यू हो सकती है, और फिर इस दूसरी टेबल पर भारी प्रश्नों को निष्पादित कर सकते हैं।

MySQL के अन्य सूचकांक भी हैं, लेकिन मुझे लगता है कि B + ट्री एक का अब तक का सबसे अधिक उपयोग किया गया है और हैश जानने के लिए एक अच्छी बात है, लेकिन आप MySQL के दस्तावेज़ में दूसरे को ढूंढ सकते हैं ।

मैं आपको "उच्च प्रदर्शन MySQL" पुस्तक को पढ़ने के लिए अत्यधिक सलाह देता हूं, उपरोक्त उत्तर निश्चित रूप से अनुक्रमित के बारे में अपने अध्याय पर आधारित था।


2
निम्नलिखित मामलों में उपरोक्त मामलों में लाभ होगा? 1। SELECT last_name, first_name FROM person WHERE last_name= "Constantine" 2.SELECT last_name, first_name FROM person WHERE last_name LIKE "%Constantine"
अक्षय तरु

1
पहली क्वेरी होगी, दूसरी क्वेरी नहीं होगी। EXPLAIN का उपयोग करें: dev.mysql.com/doc/refman/5.5/en/explain.html MySQL के साथ दूसरी क्वेरी इंडेक्स करने के लिए, आपको FULLTEXT
एमिलियो निकोलस

5
मैंने आपको अपडाउन किया क्योंकि आप 127 पर थे और # 1 उत्तर 256 पर था। मैं सब कुछ अच्छा और साफ, बाइनरी-वार करने से नहीं बच सकता था।
पब्ब्नी ११'१६ को

यह मेरे लिए नई जानकारी थी "आदेश है कि आप इन फ़ील्ड्स को क्वेरी करते हैं बहुत मायने रखता है।" धन्यवाद।
खत्री

1
@pbarney तीन वर्षों के बाद वे क्रमशः 256 और 512 के पास हैं, जिसे मैं बाइनरी-वार वृद्धि कहता हूं!
नैनोकव

43

मूल रूप से एक सूचकांक आपके सभी कुंजी का एक नक्शा है जो क्रम में क्रमबद्ध होता है। क्रम में एक सूची के साथ, फिर हर कुंजी की जांच करने के बजाय, यह इस तरह से कुछ कर सकता है:

1: सूची के मध्य में जाएं - जो मैं देख रहा हूं उससे अधिक या कम है?

2: यदि उच्चतर है, तो मध्य और नीचे के बीच आधे बिंदु पर जाएं, यदि निम्न, मध्य और शीर्ष

3: उच्च या निम्न है? फिर से मध्य बिंदु पर जाएं, आदि।

उस तर्क का उपयोग करके, आप प्रत्येक आइटम की जांच करने के बजाय, लगभग 7 चरणों में एक हल की गई सूची में एक तत्व पा सकते हैं।

जाहिर है जटिलताएं हैं, लेकिन यह आपको मूल विचार देती है।


29
इसे बाइनरी सर्च कहा जाता है।
ddlshack

धन्यवाद, अंत में एक उत्तर जो बताता है कि यह जल्दी क्यों है और न कि कैसे डीबी इंडेक्स के साथ काम करता है।
गेर्शोन हरकेजग

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

सबसे आम MySQL इंडेक्स एक B + ट्री है जो बाइनरी सर्च के समान ही काम करता है लेकिन काफी समान नहीं है। एल्गोरिथम की जटिलता समान है लेकिन जिस तरह से यह खोज करता है वह नहीं है। देखें en.wikipedia.org/wiki/B-tree
मैट

4

इस लिंक पर एक नज़र: http://dev.mysql.com/doc/refman/5.0/en/mysql-indmanes.html

वे कैसे काम करते हैं, एक एसओ पद पर कवर करने के लिए एक विषय से बहुत व्यापक है।

यहाँ उन सबसे अच्छे स्पष्टीकरणों में से एक है जिन्हें मैंने देखा है। दुर्भाग्य से यह SQL सर्वर के लिए है न कि MySQL के लिए। मुझे यकीन नहीं है कि दोनों कैसे समान हैं ...


2
अच्छा लेख। मैं SQL सर्वर नहीं जानता, लेकिन मूल कामकाज बहुत समान दिखते हैं। (मेटानोट: 2 लिंक किए गए लेख में सीएसएस शैलियों को अक्षम करना सामग्री को
अनहाइड

3

पर ले लो इस अनुक्रमण के बारे में अधिक जानकारी के लिए वीडियो

सरल अनुक्रमण आप एक तालिका पर एक अद्वितीय सूचकांक बना सकते हैं। एक अद्वितीय सूचकांक का मतलब है कि दो पंक्तियों में समान सूचकांक मान नहीं हो सकता है। यहां एक टेबल पर एक इंडेक्स बनाने का सिंटैक्स है

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);

इंडेक्स बनाने के लिए आप एक या अधिक कॉलम का उपयोग कर सकते हैं। उदाहरण के लिए, हम tutorials_tbltutorial_author का उपयोग करके एक इंडेक्स बना सकते हैं ।

CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)

आप एक मेज पर एक साधारण सूचकांक बना सकते हैं। सरल इंडेक्स बनाने के लिए क्वेरी से केवल UNIQUE कीवर्ड को छोड़ें। सरल सूचकांक एक तालिका में डुप्लिकेट मानों की अनुमति देता है।

यदि आप किसी कॉलम में मूल्यों को अनुक्रमित करना चाहते हैं, तो आप कॉलम नाम के बाद आरक्षित शब्द DESC जोड़ सकते हैं।

mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)

1
ढेर अतिप्रवाह में आपका स्वागत है! मैंने नोट किया है कि आपके सभी उत्तर आपके अपने वीडियो से लिंक होते हैं। कृपया ध्यान दें कि ओवर सेल्फ प्रमोशन की अनुमति नहीं है
एसएल बर्थ -

वह अपने वीडियो का प्रचार करना चाहते हैं। LOL
इलियास करीम

1

मैं अपने 2 सेंट जोड़ना चाहता हूं। मैं एक डेटाबेस विशेषज्ञ होने से बहुत दूर हूं, लेकिन मैंने हाल ही में इस विषय पर थोड़ा पढ़ा है; मेरे लिए कोशिश करने और एक ELI5 देने के लिए पर्याप्त है। तो, यहाँ आम आदमी की व्याख्या हो सकती है।


मैं इसे इस तरह से समझता हूं कि एक सूचकांक आपकी तालिका के एक मिनी-दर्पण की तरह है, एक साहचर्य सरणी की तरह। यदि आप इसे एक मिलान कुंजी के साथ खिलाते हैं तो आप बस एक "कमांड" में उस पंक्ति पर जा सकते हैं।

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

एक इंडेक्स होने से कंटेंट की "डाउनसाइड" (उस मिनी-मिरर के लिए) होती है, जिसके बदले में कंटेंट को तेजी से देखने के "उल्टा" होता है।

ध्यान दें कि (db इंजन की निर्भरता में) प्राथमिक, विदेशी या अद्वितीय कुंजी बनाने के लिए स्वचालित रूप से एक संबंधित सूचकांक भी सेट होता है। यही सिद्धांत मूल रूप से क्यों और कैसे काम करते हैं।


1

उत्तरों की सूची में कुछ दृश्य प्रतिनिधित्व जोड़ना। यहां छवि विवरण दर्ज करें

MySQL अप्रत्यक्ष की एक अतिरिक्त परत का उपयोग करता है: माध्यमिक सूचकांक रिकॉर्ड प्राथमिक सूचकांक रिकॉर्ड को इंगित करता है, और प्राथमिक सूचकांक स्वयं ऑन-डिस्क पंक्ति स्थानों को रखता है। यदि एक पंक्ति बदलती है, तो केवल प्राथमिक सूचकांक को अद्यतन करने की आवश्यकता है।

कैविएट: डिस्क डेटा संरचना आरेख में सपाट दिखती है लेकिन वास्तव में एक बी + वृक्ष है।

स्रोत: लिंक


1

MySQL InnoDB में, दो प्रकार के सूचकांक हैं।

  1. प्राथमिक कुंजी जिसे क्लस्टर इंडेक्स कहा जाता है। सूचकांक कुंजी शब्द B + ट्री लीफ नोड में वास्तविक रिकॉर्ड डेटा के साथ संग्रहीत होते हैं।

  2. माध्यमिक कुंजी जो गैर क्लस्टर सूचकांक है। ये इंडेक्स केवल प्राथमिक कुंजी के शब्दों को बी + ट्री लीफ नोड में अपने स्वयं के इंडेक्स कुंजी शब्दों के साथ संग्रहीत करते हैं। इसलिए द्वितीयक सूचकांक से खोज करते समय, यह सबसे पहले अपने प्राथमिक कुंजी सूचकांक कुंजी शब्दों को खोजेगा और वास्तविक डेटा रिकॉर्ड को खोजने के लिए प्राथमिक कुंजी B + ट्री को स्कैन करेगा। यह प्राथमिक सूचकांक खोज की तुलना में माध्यमिक सूचकांक को धीमा कर देगा। हालाँकि, यदि selectस्तंभ सभी द्वितीयक सूचकांक में हैं, तो फिर से प्राथमिक सूचकांक B + ट्री को देखने की कोई आवश्यकता नहीं है। इसे कवरिंग इंडेक्स कहा जाता है।

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