अनुक्रमित में स्तंभों का क्रम कितना महत्वपूर्ण है?


173

मैंने सुना है कि आपको उन स्तंभों को रखना चाहिए जो सूचकांक घोषणा की शुरुआत में सबसे अधिक चयनात्मक होंगे। उदाहरण:

CREATE NONCLUSTERED INDEX MyINDX on Table1
(
   MostSelective,
   SecondMost,
   Least
)

सबसे पहले, क्या मैं सही कह रहा हूँ? यदि हां, तो क्या मुझे अपने सूचकांक में स्तंभों के क्रम को पुनर्व्यवस्थित करके प्रदर्शन में बड़े अंतर देखने की संभावना है या यह "अच्छा करने के लिए अच्छा" अभ्यास है?

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

जवाबों:


193

इस तरह एक सूचकांक को देखो:

Cols
  1   2   3
-------------
|   | 1 |   |
| A |---|   |
|   | 2 |   |
|---|---|   |
|   |   |   |
|   | 1 | 9 |
| B |   |   |
|   |---|   |
|   | 2 |   |
|   |---|   |
|   | 3 |   |
|---|---|   |

देखें कि ए पहले पर कैसे प्रतिबंधित होता है, क्योंकि आपका पहला कॉलम पहले दूसरे कॉलम पर रोक लगाने से ज्यादा परिणाम निकालता है? यह आसान है अगर आप चित्र बनाते हैं कि सूचकांक को पार कैसे किया जाना चाहिए, स्तंभ 1, फिर स्तंभ 2, आदि ... आप देखते हैं कि मुट्ठी के पास के अधिकांश परिणामों को बंद करने से दूसरा चरण बहुत तेज हो जाता है।

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

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

संक्षेप में: नहीं, यह दिखाने के लिए नहीं है, वास्तविक प्रदर्शन लाभ हैं।


13
ऊपर की तस्वीर में, ध्यान रखें कि यदि सूचकांक 1 क्वेरी में निर्दिष्ट किया गया था, तो यह सूचकांक केवल फायदेमंद होगा। यदि आपकी क्वेरी केवल जुड़ने या खोज में कॉलम 2 को निर्दिष्ट करती है तो यह फायदेमंद नहीं होगा। इसलिए वहां भी मामले दर्ज करें। हो सकता है कि वह बिना कहे चला जाए, लेकिन उसका उल्लेख करना चाहता था।
CodeCowboyOrg

3
यह भी ध्यान रखें, मान लें कि आपका सूचकांक ऊपर दिए गए चित्र की तरह है, और कॉलम 1 और कॉलम 2 पर आपकी क्वेरी फ़िल्टर करती है, लेकिन कॉलम 2 अधिक अद्वितीय है और आप वास्तव में जो फ़िल्टर करना चाहते हैं वह वास्तव में कॉलम 2 है, फिर इसका अधिक लाभ सिर्फ एक सूचकांक के लिए है जहां कॉलम 2 पहले है। यह उल्टा लग सकता है, लेकिन ध्यान रखें कि एक इंडेक्स कई पृष्ठों पर संग्रहीत होता है और कई प्रकार के मूल्यों वाला एक पेड़ होता है, जबकि कॉलम 1 ऊपर 1/2 संभावनाओं को नकारता है, इंडेक्स पहले से जानता है कि किस इंडेक्स पेज के लिए सीधे जाना है Column2 मान, सेट को संकीर्ण करने के लिए Column 1 की आवश्यकता नहीं है।
कोडकोबॉयऑर्ग

4
यह चित्र इंडेक्स कैसे संरचित या नेविगेट किया गया है, इसका सटीक प्रतिनिधित्व नहीं है। Have एक जवाब यह सुधार प्रस्तुत stackoverflow.com/a/39080819/73226
मार्टिन स्मिथ

6
@MartinSmith मैं असहमत हूँ कि यह गलत है। यह बहुत ही सामान्य रूप से अत्यंत सरल है, जो मेरा इरादा था। स्तरों के बारे में अधिक विस्तार से खुदाई करने वाले आपके उत्तर की सराहना की जाती है, हालांकि, उन लोगों के लिए जो इसमें गहरी खुदाई करना चाहते हैं। यदि आप अपनी पेड़ की छवि को देखते हैं, तो आप देखेंगे कि मैं बहुत सरल तरीके से क्या बता रहा हूं । यह बहुत विशिष्ट या SQL विशिष्ट नहीं है; इतनी सारी चीजों में बी-ट्री इंडेक्सिंग बहुत आम है।
निक Craver

@MartinSmith मैं यह भी असहमत हूं कि यह गलत है, आप जो वर्णन कर रहे हैं वह सूचकांक को कवर करने के तरीके का मानक व्यवहार है - चयनात्मकता अधिक महत्वपूर्ण है एक बार जब आप रेंज क्वेश्चन कर रहे होते हैं क्योंकि यह इंडेक्स पेजों की संख्या को कम करता है जो कि अनुकूलक स्कैन करना चाहिए; यह बड़ी पंक्तियों में लाखों पंक्तियों के साथ महत्वपूर्ण हो सकता है
पॉल हैचर

127

स्तंभों का क्रम महत्वपूर्ण है। अब कौन सा क्रम सही है यह इस बात पर निर्भर करता है कि आप इसे कैसे क्वेरी करने जा रहे हैं। एक इंडेक्स का उपयोग सटीक खोज या रेंज स्कैन करने के लिए किया जा सकता है। एक सटीक तलाश तब होती है जब सूचकांक में सभी स्तंभों के लिए मान निर्दिष्ट किए जाते हैं और पंक्ति पर बिलकुल भूमि की रुचि होती है। इसके लिए स्तंभों का क्रम अप्रासंगिक है। एक रेंज स्कैन तब होता है जब केवल कुछ कॉलम निर्दिष्ट किए जाते हैं, और इस मामले में जब ऑर्डर महत्वपूर्ण हो जाता है। SQL सर्वर किसी श्रेणी स्कैन के लिए एक इंडेक्स का उपयोग केवल तभी कर सकता है जब बायाँ स्तम्भ निर्दिष्ट किया जाता है, और उसके बाद ही यदि अगला बायाँ स्तम्भ निर्दिष्ट किया जाता है, और इसी तरह। यदि आपके पास (ए, बी, सी) पर एक सूचकांक है, तो इसका उपयोग स्कैन के लिए किया जा सकता है A=@a, A=@a AND B=@bलेकिन इसके लिए नहींB=@b , C=@cन ही B=@b AND C=@c। मामला A=@a AND C=@cमिश्रित है, जैसे किA=@aभाग सूचकांक का उपयोग करेगा, लेकिन C=@cनहीं (क्वेरी सभी बी मानों को स्कैन A=@aकरेगा, 'छोड़ें नहीं' C=@c)। अन्य डेटाबेस सिस्टम में तथाकथित 'स्किप स्कैन' ऑपरेटर होता है जो बाहरी कॉलम निर्दिष्ट नहीं होने पर एक इंडेक्स में आंतरिक कॉलम का कुछ लाभ ले सकता है।

हाथ में उस ज्ञान के साथ आप सूचकांक की परिभाषाओं को फिर से देख सकते हैं। एक सूचकांक (MostSelective, SecondMost, Least)तभी प्रभावी होगा जब MostSelectiveकॉलम निर्दिष्ट किया जाएगा। लेकिन यह सबसे अधिक चयनात्मक होने के कारण, आंतरिक स्तंभों की प्रासंगिकता जल्दी ही ख़राब हो जाएगी। बहुत बार आप पाएंगे कि एक बेहतर सूचकांक चालू (MostSelective) include (SecondMost, Least)या चालू है (MostSelective, SecondMost) include (Least)। क्योंकि आंतरिक स्तंभ कम प्रासंगिक हैं, इसलिए इंडेक्स में इस तरह के सही पदों पर कम चयनात्मकता वाले कॉलम रखने से उन्हें कुछ नहीं मिलता है, लेकिन यह किसी भी तरह से मध्यवर्ती पृष्ठों से बाहर निकलने और उन्हें केवल पत्ती पृष्ठों पर रखने के लिए समझ में आता है, क्वेरी कवर करने के उद्देश्य। दूसरे शब्दों में, उन्हें INCLUDE में स्थानांतरित करें। Leastस्तंभ का आकार बढ़ने पर यह अधिक महत्वपूर्ण हो जाता है । विचार यह है कि यह सूचकांक केवल उन प्रश्नों का लाभ उठा सकता है जो निर्दिष्ट करते हैंMostSelective या तो एक सटीक मूल्य या एक सीमा के रूप में, और वह कॉलम सबसे अधिक चयनात्मक होने के नाते यह पहले से ही उम्मीदवार पंक्तियों को काफी हद तक प्रतिबंधित करता है।

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

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


3
हमेशा की तरह रेमस की तरह शानदार प्रतिक्रिया। मैं आपके तीसरे पैराग्राफ पर कुछ और बार पढ़ने जा रहा हूं और फॉलो करूंगा। मुझे संदेह है कि हो सकता है कि मुझे क्या करना है।
अबे मिसेलर

"एसक्यूएल सर्वर एक इंडेक्स स्कैन के लिए एक इंडेक्स का उपयोग केवल तभी कर सकता है जब बाईं ओर का कॉलम निर्दिष्ट किया जाता है, और उसके बाद ही यदि अगला बाईं ओर का कॉलम निर्दिष्ट किया जाता है, और इसी तरह।" यह वास्तव में मेरी समझ से गायब था, धन्यवाद! मुझे नहीं पता था कि रेंज स्कैन केवल सबसे सही इस्तेमाल किए गए इंडेक्स कॉलम पर किया जा सकता है, लेकिन अब जब मैं करता हूं तो यह बहुत मायने रखता है।
Allon Guralnek

क्या यह स्पष्टीकरण ओरेकल डीबी के लिए लागू है?
एक और

1
@Roizpi हां, यह मूल रूप से इंडेक्स के साथ किसी भी संबंध डेटाबेस के समान या बहुत समान तरीके से काम कर रहा है।
ताट्रांसकेमिड्वेन

45

जैसा कि रेमस कहता है कि यह आपके कार्यभार पर निर्भर करता है।

मैं हालांकि स्वीकृत उत्तर के एक भ्रामक पहलू को संबोधित करना चाहता हूं।

सूचकांक में सभी स्तंभों पर समानता खोज करने वाले प्रश्नों के लिए कोई महत्वपूर्ण अंतर नहीं है।

नीचे दो तालिकाएँ बनाई गई हैं और उन्हें समान डेटा के साथ पॉप्युलेट किया गया है। अंतर केवल इतना है कि किसी के पास कम से कम चयनात्मक और दूसरे से रिवर्स के लिए ऑर्डर की गई चाबियां हैं।

CREATE TABLE Table1(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);
CREATE TABLE Table2(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);

CREATE NONCLUSTERED INDEX MyINDX on Table1(MostSelective,SecondMost,Least);
CREATE NONCLUSTERED INDEX MyINDX2 on Table2(Least,SecondMost,MostSelective);

INSERT INTO Table1 (MostSelective, SecondMost, Least)
output inserted.* into Table2
SELECT TOP 26 REPLICATE(CHAR(number + 65),800), number/5, '~'
FROM master..spt_values
WHERE type = 'P' AND number >= 0
ORDER BY number;

अब दोनों टेबल के खिलाफ एक क्वेरी कर रहा है ...

SELECT *
FROM   Table1
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~';

SELECT *
FROM   Table2
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~'; 

... दोनों एक इंडेक्स फाइन का उपयोग करते हैं और दोनों को एक ही कीमत दी जाती है।

यहां छवि विवरण दर्ज करें

स्वीकृत उत्तर में ASCII कला वास्तव में नहीं है कि कैसे अनुक्रमित संरचित हैं। तालिका 1 के सूचकांक पृष्ठ नीचे दर्शाए गए हैं (पूर्ण आकार में खोलने के लिए छवि पर क्लिक करें)।

यहां छवि विवरण दर्ज करें

अनुक्रमणिका पृष्ठों में संपूर्ण कुंजी वाली पंक्तियाँ होती हैं (इस मामले में पंक्ति पहचानकर्ता के लिए वास्तव में एक अतिरिक्त कुंजी स्तंभ जोड़ा जाता है क्योंकि अनुक्रमणिका को अद्वितीय नहीं घोषित किया गया था, लेकिन इस बारे में आगे की जानकारी की उपेक्षा की जा सकती है )।

SQL सर्वर के ऊपर क्वेरी के लिए कॉलम की चयनात्मकता की परवाह नहीं करता है। यह रूट पेज की एक द्विआधारी खोज करता है और पता चलता है कि कुंजी (PPP...,3,~ ) है >=(JJJ...,1,~ )और < (SSS...,3,~ )इसलिए इसे पृष्ठ को पढ़ना चाहिए 1:118। यह तब उस पृष्ठ पर मुख्य प्रविष्टियों की एक द्विआधारी खोज करता है और नीचे जाने के लिए पत्ती पृष्ठ का पता लगाता है।

चयनात्मकता के क्रम में अनुक्रमणिका को बदलना बाइनरी सर्च से या तो पृष्ठों की संख्या या अनुक्रमणिका की तलाश करने के लिए नेविगेट करने की आवश्यकता वाले संख्याओं की अपेक्षित संख्या को प्रभावित नहीं करता है। सबसे अच्छी तरह से यह महत्वपूर्ण तुलना की तुलना में मामूली गति कर सकता है।

कभी-कभी सबसे अधिक चयनात्मक सूचकांक का आदेश देने से आपके कार्यभार में अन्य प्रश्नों के लिए समझ में आएगा।

उदाहरण के लिए, यदि कार्यभार में निम्नलिखित दोनों रूपों के प्रश्न हैं।

SELECT * ... WHERE  MostSelective = 'P'

SELECT * ...WHERE Least = '~'

ऊपर दिए गए इंडेक्स उनमें से किसी के लिए भी कवर नहीं कर रहे हैं। MostSelectiveएक सीक और लुक्स के साथ एक योजना बनाने के लिए पर्याप्त चयनात्मक है, लेकिन इसके खिलाफ क्वेरी Leastनहीं है।

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

इसके विपरीत प्रश्न

SELECT MostSelective,
       SecondMost,
       Least
FROM   Table2
WHERE  Least = '~'
ORDER  BY SecondMost,
          MostSelective 

सामान्य रूप से निर्धारित एक के विपरीत क्रम होने से मदद मिलेगी - क्योंकि यह क्वेरी को कवर करता है, बूट करने के लिए वांछित क्रम में एक सीक और रिटर्न पंक्तियों का समर्थन कर सकता है।

तो यह सलाह का एक दोहराया दोहराया टुकड़ा है, लेकिन कम से कम यह अन्य प्रश्नों के संभावित लाभ के बारे में एक अनुमान है - और यह वास्तव में आपके कार्यभार को देखने के लिए कोई विकल्प नहीं है ।


31

आपको उन स्तंभों को रखना चाहिए जो सूचकांक घोषणा की शुरुआत में सबसे अधिक चयनात्मक होंगे।

सही बात। अनुक्रमणिका कंपोजिट हो सकती है - कई कॉलम से बना है - और सबसे महत्वपूर्ण सिद्धांत के कारण क्रम महत्वपूर्ण है। कारण यह है, कि डेटाबेस सूची को बाएं से दाएं की जाँच करता है, और परिभाषित क्रम से मेल खाते हुए एक संबंधित कॉलम संदर्भ ढूंढना पड़ता है। उदाहरण के लिए, स्तंभों के साथ एक पता तालिका पर एक सूचकांक होने:

  • पता
  • Faridabad
  • राज्य

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


क्या होगा अगर यह केवल सबसे सही स्तंभ था जिसका उपयोग नहीं किया जा रहा था? इसलिए एक क्वेरी पते और शहर का उपयोग करती है, लेकिन राज्य नहीं। क्या सूचकांक का उपयोग किया जाएगा?
अबे मिसेलर

@ एबे: राइट का उपयोग नहीं किया जाएगा - आपको बाईं ओर से शुरू होने वाले सूचकांक आदेश को पूरा करना होगा। मिस एक, इसका उपयोग नहीं कर सकते।
OMG पोंजी

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

6

बाकी सभी जवाब गलत हैं।

एक समग्र सूचकांक में अलग-अलग कॉलम की चयनात्मकता ऑर्डर लेने पर कोई फर्क नहीं पड़ता।

यहां सरल विचार प्रक्रिया है: प्रभावी रूप से, एक सूचकांक में शामिल कॉलम का संयोजन है।

उस तर्क को देते हुए, एकमात्र अंतर दो 'स्ट्रिंग्स' की तुलना करता है जो पहले बनाम बाद में स्ट्रिंग में भिन्न होता है। यह कुल लागत का एक छोटा हिस्सा है। जैसा कि एक उत्तर में बताया गया है, कोई "पहला पास / दूसरा पास" नहीं है।

तो, किस क्रम का उपयोग किया जाना चाहिए?

  1. किसी भी क्रम =में परीक्षण किए गए कॉलम (एस) के साथ शुरू करें ।
  2. फिर एक श्रेणी के कॉलम पर काम करें।

उदाहरण के लिए, बहुत-कम चयनात्मकता कॉलम को इसमें पहले आना चाहिए :

WHERE deleted = 0  AND  the_datetime > NOW() - INTERVAL 7 DAY
INDEX(deleted, the_datetime)

इंडेक्स में ऑर्डर स्वैप करने पर यह पूरी तरह से नजरअंदाज हो जाएगा deleted

(स्तंभों को क्रमबद्ध करने के लिए और भी कई नियम हैं।)


क्या नकारात्मक वोट क्योंकि मैं गलत हूं? या इसलिए कि मेरे पास एक मजबूत राय है? या कुछ और?
रिक जेम्स

मेरी नीचता नहीं थी, लेकिन हटा दिया गया = मुझे लगता है कि यह कम चयनात्मकता नहीं है? मुझे लगता है कि यह मेज में पंक्तियों का बहुमत होगा।
ग्रेग

@Greg - मुझे लगता है कि इसका मतलब है "कम चयनात्मकता" - अर्थात, deletedअवांछित पंक्तियों को फ़िल्टर करने में बहुत मदद नहीं करता है। क्या आपके पास एक बेहतर उदाहरण है? (यह वही है जो मेरे दिमाग में तब आया जब मैंने उत्तर लिखा।)
रिक जेम्स

मेरी ओर से गलतफहमी।
ग्रेग

1
@ClickOk - धन्यवाद। मेरी रसोई की किताब कुछ बुनियादी जानकारी देती है: mysql.rjweb.org/doc.php/index_cookbook_mysql
रिक जेम्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.