MySQL अनुक्रमित - सबसे अच्छे अभ्यास क्या हैं?


208

मैं कुछ समय के लिए अपने MySQL डेटाबेस पर अनुक्रमित का उपयोग कर रहा हूं लेकिन कभी भी उनके बारे में ठीक से नहीं सीखा है। आम तौर पर मैं किसी भी फ़ील्ड पर एक इंडेक्स डालता हूं जिसे मैं एक WHEREक्लॉज़ का उपयोग करके खोज या चयन करूंगा लेकिन कभी-कभी यह इतना काला और सफेद नहीं लगता है।

MySQL अनुक्रमित के लिए सर्वोत्तम अभ्यास क्या हैं?

उदाहरण स्थितियों / दुविधाओं:

  • यदि किसी तालिका में छह कॉलम हैं और उनमें से सभी खोज योग्य हैं, तो क्या मुझे उन सभी को अनुक्रमित करना चाहिए या उनमें से कोई भी नहीं?

  • अनुक्रमण के नकारात्मक प्रदर्शन प्रभाव क्या हैं?

  • अगर मेरे पास VARCHAR 2500 स्तंभ है जो मेरी साइट के कुछ हिस्सों से खोजा जा सकता है, तो क्या मुझे इसे अनुक्रमित करना चाहिए?


5
आपको शायद इस सवाल का जवाब देना चाहिए। किसी भी डेटाबेस मॉडल के अनुकूलन के लिए इंडेक्स का चुनाव एक महत्वपूर्ण हिस्सा है। और मेरे विचार से php से असंबंधित है।
VGE


जवाबों:


242

आपको निश्चित रूप से अनुक्रमण पर पढ़ने में कुछ समय बिताना चाहिए, इसके बारे में बहुत कुछ लिखा है, और यह समझना महत्वपूर्ण है कि क्या हो रहा है।

मोटे तौर पर, एक सूचकांक एक तालिका की पंक्तियों पर एक आदेश देता है।

सादगी के लिए, एक मेज की कल्पना करें बस एक बड़ी CSV फ़ाइल है। जब भी कोई पंक्ति डाली जाती है, उसे अंत में डाला जाता है । तो तालिका का "प्राकृतिक" क्रम केवल वह क्रम है जिसमें पंक्तियाँ डाली गई थीं।

कल्पना कीजिए कि आपने CSV फ़ाइल को बहुत ही अल्पविकसित स्प्रेडशीट एप्लिकेशन में लोड किया है। यह सब स्प्रेडशीट डेटा प्रदर्शित करता है, और क्रम में पंक्तियों को क्रमबद्ध करता है।

अब कल्पना करें कि आपको उन सभी पंक्तियों को खोजने की आवश्यकता है जिनके तीसरे स्तंभ में कुछ मूल्य "एम" है। आपके पास जो उपलब्ध है, उसे देखते हुए आपके पास केवल एक विकल्प है। आप प्रत्येक पंक्ति के लिए तीसरे स्तंभ के मान की जाँच करते हुए तालिका को स्कैन करते हैं। यदि आपको बहुत सी पंक्तियाँ मिली हैं, तो यह विधि (एक "टेबल स्कैन") एक लंबा समय ले सकती है!

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

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

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

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

दूसरी ओर, रीड बहुत तेज हो जाते हैं।

उम्मीद है कि आपके पहले दो प्रश्नों को शामिल किया गया है (जैसा कि अन्य ने उत्तर दिया है - आपको सही संतुलन खोजने की आवश्यकता है)।

आपका तीसरा परिदृश्य थोड़ा और जटिल है। यदि आप LIKE का उपयोग कर रहे हैं, तो अनुक्रमण इंजन आमतौर पर आपकी रीड स्पीड को पहले "%" तक बढ़ाने में मदद करेंगे। दूसरे शब्दों में, यदि आप ''%% बार% 'कॉलम का चयन कर रहे हैं, तो डेटाबेस सभी पंक्तियों को खोजने के लिए सूचकांक का उपयोग करेगा जहां कॉलम "फू" से शुरू होता है, और फिर सब्मिट खोजने के लिए उस मध्यवर्ती पंक्तियों को स्कैन करने की आवश्यकता होती है। जिसमें "बार" शामिल है। चुनें ... जहां कॉलम '% बार%' सूचकांक का उपयोग नहीं कर सकता। मुझे आशा है कि आप देख सकते हैं क्यों।

अंत में, आपको एक से अधिक कॉलम पर अनुक्रमित के बारे में सोचना शुरू करना होगा। अवधारणा समान है, और समान सामान के समान व्यवहार करती है - अनिवार्य रूप से, यदि आपके पास (ए, बी, सी) पर एक सूचकांक है, तो इंजन बाएं से दाएं सबसे अच्छा के रूप में सूचकांक का उपयोग करना जारी रखेगा। तो कॉलम पर एक खोज एक (ए, बी, सी) सूचकांक का उपयोग कर सकती है, जैसा कि एक (ए, बी) पर होगा। हालाँकि, यदि आप WHERE = 5 और c = 1 खोज रहे हैं तो इंजन को एक पूर्ण टेबल स्कैन करने की आवश्यकता होगी

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


10
FULLTEXTइंडेक्स के बारे में क्या ? क्या वे जैसी स्थितियों के साथ मदद कर सकते हैं LIKE '%bar%'?
सेप्टाग्राम

2
@Septagram - FULLTEXTसाथ मदद कर सकते हैं कि क्वेरी यदि bar एक "शब्द" है। FULLTEXTशब्दों को संभालता है, न कि मनमाने ढंग से सब्सट्रिंग (जैसा LIKEकरता है)।
रिक जेम्स

@timdev स्पष्ट रूप से किस भाग में पहले प्रश्न का उत्तर दिया गया था? मैं आपके बहुमूल्य उत्तर के पहले और दूसरे भाग में दिए गए दूसरे और तीसरे प्रश्नों का पता लगा सकता हूँ (पूर्व और बाद में उम्मीद है कि आपके पहले दो प्रश्नों को शामिल करता है )
मैनुअल जॉर्डन

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

57

इंडेक्सिंग की कला और अधिक माहिर की तरह प्रस्तुतियों की जाँच करें ।

अपडेट 12/2012: मैंने अपनी एक नई प्रस्तुति पोस्ट की है: हाउ टू डिजाइन इंडेक्स, रियली । मैंने अक्टूबर 2012 में सांता क्लारा में ज़ेंडकॉन में और दिसंबर 2012 में पेरकोना लाइव लंदन में इसे प्रस्तुत किया।

सबसे अच्छा इंडेक्स डिजाइन करना एक ऐसी प्रक्रिया है, जो आपके ऐप में आपके द्वारा चलाए जाने वाले प्रश्नों से मेल खाती है।

किसी भी सामान्य-उद्देश्य के नियमों की अनुशंसा करना कठिन है, जिनके बारे में कॉलम अनुक्रमणिका के लिए सबसे अच्छे हैं, या क्या आपको सभी स्तंभों को अनुक्रमित करना चाहिए, कोई स्तंभ नहीं, जिन्हें अनुक्रमणिकाओं को कई स्तंभों को जोड़ना चाहिए, आदि। यह उन प्रश्नों पर निर्भर करता है जिन्हें आपको चलाने की आवश्यकता है।

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

एक स्तंभ के लिए जो VARCHAR (2500) है, आप शायद एक पूर्ण सूचकांक या उपसर्ग सूचकांक का उपयोग करना चाहते हैं :

CREATE INDEX i ON SomeTable(longVarchar(100));

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


3
बहुत बहुत धन्यवाद। स्लाइडशेयर . net/matsunobu/… वास्तव में बहुत मददगार थी।
बिशाल पौडेल



1
अद्भुत प्रस्तुति (2012 से एक), वास्तव में सूचकांक के पूरे बिंदु को समझ गया।
डार्कतेक

46

मैं अन्य उत्तरों में कुछ अच्छी सलाह नहीं दूंगा, लेकिन जोड़ूंगा:

यौगिक संकेत

आप यौगिक सूचकांक बना सकते हैं - एक सूचकांक जिसमें कई कॉलम शामिल हैं। MySQL बायें से दायें इन का उपयोग कर सकते हैं । इसलिए यदि आपके पास:

Table A
Id
Name
Category
Age
Description

यदि आपके पास एक कंपाउंड इंडेक्स है जिसमें उस क्रम में नाम / श्रेणी / आयु शामिल है, तो ये कहां खंड सूचकांक का उपयोग करेंगे:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

परंतु

WHERE Category='A' and Age > 18

उस सूचकांक का उपयोग नहीं करेंगे क्योंकि सब कुछ बाएं से दाएं उपयोग किया जाना है।

समझाना

MySQL के लिए कौन से सूचकांक उपलब्ध हैं और यह वास्तव में किसका चयन करता है, यह समझने के लिए एक्सप्लेन / एक्सप्लेन का उपयोग करें। MySQL का ही उपयोग करेगा प्रति प्रश्न एक कुंजी का

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

धीमी क्वेरी लॉग

चालू धीमी क्वेरी लॉग जिन तक प्रश्नों धीमी गति से चल रहे हैं देखने के लिए।

चौड़ा स्तंभ

यदि आपके पास एक विस्तृत स्तंभ है जहां अंतर का MOST पहले कई पात्रों में होता है, तो आप अपने सूचकांक में केवल पहले N वर्णों का उपयोग कर सकते हैं। उदाहरण: हमारे पास एक रेफरनंबर कॉलम है जिसे वर्चर (255) के रूप में परिभाषित किया गया है, लेकिन 97% मामलों में, संदर्भ संख्या 10 वर्ण या उससे कम है। मैंने पहले 10 वर्णों को देखने के लिए सूचकांक को बदल दिया और प्रदर्शन में थोड़ा सुधार किया।


मेरे पास पिछले भाग के बारे में एक प्रश्न है। मैंने कहीं पढ़ा है कि अगर आप VARCHAR के साथ एक कॉलम बनाते हैं, तो आपको इसे हमेशा 255 पर सेट करना चाहिए। अब आपने कहा कि इस प्रकार के कॉलम के लिए सेट किया गया इंडेक्स केवल पहले 10 अक्षरों को देखने तक सीमित हो सकता है। आप वास्तव में ऐसा कैसे कर सकते हैं?
एलेक्सियोवे

20

यदि किसी तालिका में छह कॉलम हैं और उनमें से सभी खोज योग्य हैं, तो क्या मुझे उन सभी या उनमें से किसी को भी अनुक्रमित करना चाहिए

क्या आप फ़ील्ड के आधार पर किसी फ़ील्ड पर खोज कर रहे हैं या कुछ खोज कई फ़ील्ड का उपयोग कर रहे हैं? किन क्षेत्रों में सबसे अधिक खोज की जा रही है? फ़ील्ड प्रकार क्या हैं? (उदाहरण के लिए VARCHAR पर सूचकांक की तुलना में सूचकांक बेहतर काम करता है) क्या आपने उन प्रश्नों पर EXPLAIN का उपयोग करने की कोशिश की है जो चलाए जा रहे हैं?

अनुक्रमण के नेगेटिव प्रदर्शन प्रभाव क्या हैं

UPDATE और INSERTs धीमे होंगे वहाँ भी अतिरिक्त भंडारण स्थान requirments है, लेकिन है कि इन दिनों सामान्य महत्वहीन है।

अगर मेरे पास VARCHAR 2500 स्तंभ है जो मेरी साइट के कुछ हिस्सों से खोजा जा सकता है, तो क्या मुझे इसे अनुक्रमित करना चाहिए

नहीं, जब तक कि यह अद्वितीय नहीं है (जिसका अर्थ है कि यह पहले से ही अनुक्रमित है) या आप केवल उस क्षेत्र पर सटीक मैचों की खोज करते हैं (LIKE या mySQL के पूर्ण खोज का उपयोग नहीं करते हैं)।

आम तौर पर मैं किसी भी फ़ील्ड पर एक इंडेक्स डालता हूं जिसे मैं WHERE क्लॉज़ का उपयोग करके खोज या चयन करूंगा

मैं सामान्य रूप से उन क्षेत्रों को अनुक्रमणित करूँगा जो सबसे अधिक जटिल हैं, और फिर INT / BOOLEANs / ENUMs बल्कि वे फ़ील्ड जो VARCHARS हैं। मत भूलो, अक्सर आपको संयुक्त फ़ील्ड पर एक इंडेक्स बनाने की आवश्यकता होती है, बजाय एक व्यक्तिगत फ़ील्ड पर एक इंडेक्स के। EXPLAIN का उपयोग करें, और धीमी लॉग की जाँच करें।


11

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

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

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

Takeaway: इंडेक्स से अधिक नहीं


5

सामान्य तौर पर, सूचकांक अतिरिक्त डिस्क स्थान का उपयोग करने और INSERT/ UPDATE/ DELETEप्रश्नों को धीमा करने के नुकसान के साथ, स्पीडअप डेटाबेस खोज में मदद करते हैं । EXPLAINजब MySQL आपके सूचकांकों का उपयोग करता है, तो यह जानने के लिए परिणामों का उपयोग करें और पढ़ें।

यदि किसी तालिका में छह कॉलम हैं और उनमें से सभी खोज योग्य हैं, तो क्या मुझे उन सभी को अनुक्रमित करना चाहिए या उनमें से कोई भी नहीं?

सभी छह स्तंभों को अनुक्रमित करना हमेशा सबसे अच्छा अभ्यास नहीं होता है।

(ए) क्या आप उन कॉलमों में से किसी का उपयोग करने जा रहे हैं, जब आप विशिष्ट जानकारी खोज रहे हैं?

(ख) उन स्तंभों की चयनात्मकता क्या है (तालिका में रिकॉर्ड की कुल राशि की तुलना में कितने अलग-अलग मूल्य संग्रहीत हैं)?

MySQL एक लागत-आधारित ऑप्टिमाइज़र का उपयोग करता है, जो क्वेरी करते समय "सबसे सस्ता" रास्ता खोजने की कोशिश करता है। और कम चयनात्मकता वाले क्षेत्र अच्छे उम्मीदवार नहीं हैं।

अनुक्रमण के नेगेटिव प्रदर्शन प्रभाव क्या हैं?

पहले से ही उत्तर दिया गया: अतिरिक्त डिस्क स्थान, डालने के दौरान कम प्रदर्शन - अपडेट - हटाएं।

अगर मेरे पास VARCHAR 2500 स्तंभ है जो मेरी साइट के कुछ हिस्सों से खोजा जा सकता है, तो क्या मुझे इसे अनुक्रमित करना चाहिए?

FULLTEXT इंडेक्स आज़माएं ।


4

1/2) इंडेक्स कुछ चुनिंदा ऑपरेशंस को गति देता है, लेकिन वे अन्य ऑपरेशन जैसे इन्सर्ट, अपडेट और डिलीट को धीमा कर देते हैं। यह एक अच्छा संतुलन हो सकता है।

3) एक पूर्ण पाठ सूचकांक या शायद स्फिंक्स का उपयोग करें


slow down other operations like insert, update and deletesआप इसे रोकने के लिए उपयोग कर सकते हैं START TRANSACTION; YOUR CODE HERE; COMMIT जो slowing downअन्य कार्यों से बचने में मदद कर सकता है , क्योंकि यह केवल एक बार एक बाधा की जांच करेगा। चेतावनी: यदि आप का उपयोग करते हैं REPLACE INTOऔर अपने SQL_MODE<> STRICT_ALL_TABLESया अनदेखी करेंगे में और डुप्लिकेट डालने की जगह। TRADITIONALBulk Load
JayRizzo

सभी MySQL इंजन में लेन-देन समर्थित नहीं हैं। AFAIK, लेन-देन DB कार्यों को धीमा कर देता है, भले ही वे केवल अंतर्निहित रूप से उपयोग किए जाते हों। वास्तविक प्रदर्शन के आधार पर हमें जो डिजाइन करने की आवश्यकता है, वह अनुक्रमणिका और लेनदेन सहित विभिन्न अनुकूलन विकल्पों के प्रोफाइल (प्रदर्शन को मापने) का कुछ अर्ध-स्वचालित तरीका है।
डेविड स्पेक्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.