सूचकांक बनाते समय INCLUDE क्लॉज का उपयोग क्यों करें?


431

70-433 परीक्षा के लिए अध्ययन करते समय मैंने देखा कि आप निम्नलिखित दो तरीकों में से एक में एक कवरिंग इंडेक्स बना सकते हैं।

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)

- या

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)

INCLUDE क्लॉज मेरे लिए नया है। आप इसका उपयोग क्यों करेंगे और INCLUDE क्लॉज के साथ या उसके बिना एक कवरिंग इंडेक्स बनाने के लिए क्या दिशा-निर्देश निर्धारित करने में आप क्या सुझाव देंगे?

जवाबों:


363

यदि स्तंभ में नहीं है WHERE/JOIN/GROUP BY/ORDER BY, लेकिन केवल SELECTखंड में कॉलम सूची में है ।

यह INCLUDEखंड इंडेक्स ट्री के बजाय डेटा सबसे निचले / पत्ती स्तर पर डेटा जोड़ता है। यह इंडेक्स को छोटा बनाता है क्योंकि यह पेड़ का हिस्सा नहीं है

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

एक और MSDN लेख एक उदाहरण के साथ काम किया


7
तो फिर, यह एक कवर इंडेक्स का कम महंगा संस्करण बनाने के लिए एक तकनीक होगी?
JMarsch

3
@, क्या आप इस वाक्य को और अधिक विस्तार से समझाएंगे, और यह समझाएंगे कि इसका मतलब यह है कि शामिल क्लॉज छँटाई के लिए उपयोगी नहीं है, आदि: "INCLUDE क्लॉज इंडेक्स ट्री के बजाय सबसे कम / लीफ स्तर पर डेटा जोड़ता है। "यह इंडेक्स को छोटा बनाता है क्योंकि यह पेड़ का हिस्सा नहीं है"
टोला ओडेझी

4
@JMarsch: देर से जवाब के लिए खेद है, लेकिन हाँ, यह वास्तव में यही है।
gbn

10
@ टोला ओडजायि: INCLUDE कॉलम इंडेक्स में प्रमुख कॉलम नहीं हैं, इसलिए उन्हें ऑर्डर नहीं किया जाता है। यह उन्हें आमतौर पर JOINs या सॉर्टिंग के लिए उपयोगी नहीं बनाता है । और क्योंकि वे कुंजी स्तंभ नहीं हैं, वे मुख्य स्तंभों की तरह पूरे बी-ट्री संरचना में नहीं बैठते हैं
gbn

4
हालांकि यह व्यापक रूप से स्वीकार्य जवाब है, मुझे लगता है कि अधिक विवरण की जरूरत है, क्या हुआ अगर कुछ क्वेरी के लिए स्तंभ का हिस्सा है SELECTऔर कुछ के लिए नहीं \?
Chisko

215

आप INCLUDE का उपयोग गैर-संकुल अनुक्रमणिका के पत्ती स्तर में एक या अधिक कॉलम जोड़ने के लिए करेंगे, यदि ऐसा करने से आप अपने प्रश्नों को "कवर" कर सकते हैं।

कल्पना करें कि आपको एक कर्मचारी की आईडी, विभाग की आईडी और अंतिम नाम के लिए क्वेरी करने की आवश्यकता है।

SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5

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

यदि आपने उस अंतिमनाम को अपने सूचकांक में शामिल किया था:

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(EmployeeID, DepartmentID)
  INCLUDE (Lastname)

फिर आपको जो भी जानकारी चाहिए वह सभी गैर-संकुल सूचकांक के पत्ती स्तर में उपलब्ध है। बस गैर-संकुलित सूचकांक में मांग करने और किसी दिए गए विभाग के लिए अपने कर्मचारियों को खोजने से, आपके पास सभी आवश्यक जानकारी होती है, और सूचकांक में पाए जाने वाले प्रत्येक कर्मचारी के लिए बुकमार्क देखना अब आवश्यक नहीं है -> आप बहुत समय बचाते हैं।

जाहिर है, आप प्रत्येक कॉलम को प्रत्येक गैर-संकुल सूचकांक में शामिल नहीं कर सकते हैं - लेकिन अगर आपके पास ऐसे प्रश्न हैं जो "कवर" होने के लिए सिर्फ एक या दो कॉलम गायब हैं (और जो बहुत उपयोग किए जाते हैं), तो यह उन लोगों को शामिल करने में बहुत मददगार हो सकता है एक उपयुक्त गैर-संकुल सूचकांक में।


25
क्या आप वाकई इस इंडेक्स का उपयोग करेंगे? कर्मचारी क्यों? आपको केवल प्रमुख कॉलम में ही विभाग की आवश्यकता है? आपको यहाँ लेखकीय के रूप में उद्धृत किया गया है: stackoverflow.com/q/6187904/27535
gbn

3
आपकी व्याख्या अच्छी है लेकिन वास्तव में आपके द्वारा उपयोग किए जाने वाले उपयोग के मामले में नहीं है। कुंजी स्तंभ (s) JOINक्वेरी में फ़िल्टर या कुंजियों पर होना चाहिए , और INCLUDEs आपके द्वारा पुनर्प्राप्त किए जा रहे डेटा को सॉर्ट करने की आवश्यकता है।
JNK

15
सर्वप्रथम सूचकांक कर्मचारी (कर्मचारी, विभागीय) का उपयोग विभागीय विभाग को फ़िल्टर करने के लिए नहीं किया जाएगा। 5. क्योंकि इसका आदेश मेल नहीं
खा रहा है

29

यह चर्चा महत्वपूर्ण बिंदु पर गायब है: सवाल यह नहीं है कि क्या "गैर-कुंजी-कॉलम" सूचकांक -कॉलम के रूप में या शामिल किए गए -कॉलम के रूप में शामिल करना बेहतर है ।

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

  1. Id1, id2 ... idN पर अकेले इंडेक्स का उपयोग करें या
  2. Id1, id2 ... idN plus में index 1, col2 ... colN ... का प्रयोग करें

कहां: id1, id2 ... idN अक्सर प्रतिबंधों में उपयोग किए जाने वाले कॉलम हैं और col1, col2 ... कॉलन अक्सर कॉलम चुने जाते हैं, लेकिन आमतौर पर प्रतिबंधों में उपयोग नहीं किए जाते हैं

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

तो विकल्प 1 या 2 का उपयोग करें?

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

यदि आपके द्वारा शामिल किए गए कॉलमों को शामिल किए जाने पर विचार किया जाता है, तो अक्सर अपडेट किए जाते हैं ( इंडेक्स के बिना- कुंजी -कॉलमों को अपडेट किया जा रहा है) - या - यदि यह उनमें से बहुत से हैं, तो इंडेक्स आपकी तालिका की एक प्रति के करीब हो जाता है - उपयोग विकल्प 1 मैं सुझाव देता हूँ! इसके अलावा अगर कुछ शामिल-कॉलम (ओं) को जोड़ने से कोई प्रदर्शन-अंतर नहीं निकलता है - आप उन्हें जोड़ने का विचार छोड़ना चाह सकते हैं :) सत्यापित करें कि वे उपयोगी हैं!

कुंजियों में समान मान (id1, id2 ... idN) प्रति पंक्तियों की औसत संख्या कुछ महत्व की हो सकती है।

सूचना है कि यदि एक स्तंभ - यह है कि एक के रूप में जोड़ा जाता है शामिल सूचकांक के -column - में प्रयोग किया जाता है प्रतिबंध : जब तक इस तरह के रूप सूचकांक इस्तेमाल किया जा सकता (index- के खिलाफ प्रतिबंध के आधार पर कुंजी -columns) - तो एसक्यूएल सर्वर मिलान है तालिका के चारों ओर महंगा तरीका जाने के बजाय सूचकांक (पत्ती-नोड-मान) के खिलाफ स्तंभ-प्रतिबंध।


18

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


7

कारणों (सूचकांक के पत्ती स्तर में डेटा सहित) को अच्छी तरह से समझाया गया है। इसका कारण यह है कि आप इस बारे में दो झटके देते हैं, यह है कि जब आप अपनी क्वेरी चलाते हैं, यदि आपके पास अतिरिक्त कॉलम शामिल नहीं हैं (SQL 2005 में नई सुविधा) तो SQL सर्वर को अतिरिक्त कॉलम प्राप्त करने के लिए क्लस्टर इंडेक्स पर जाना पड़ता है जो अधिक समय लेता है, और SQL सर्वर सेवा, डिस्क, और मेमोरी (बफर कैश विशिष्ट होने के लिए) में अधिक लोड जोड़ता है क्योंकि नए डेटा पृष्ठ मेमोरी में लोड होते हैं, संभवतः बफर कैश से बाहर अन्य अधिक बार आवश्यक डेटा को धक्का देते हैं।


क्या यह साबित करने का कोई तरीका है कि यह वास्तव में कम मेमोरी का उपयोग कर रहा है? यह वही है जो मैं भी उम्मीद करता हूं, लेकिन मुझे काम के बारे में कुछ स्थिर हो रहा है
15

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

5

एक अतिरिक्त विचार जो मैंने पहले से दिए गए उत्तरों में नहीं देखा है, वह यह है कि इसमें शामिल कॉलम डेटा प्रकार के हो सकते हैं जिन्हें अनुक्रमणिका कुंजी कॉलम, जैसे कि varchar (अधिकतम) की अनुमति नहीं है।

यह आपको एक कवरिंग इंडेक्स में ऐसे कॉलम को शामिल करने की अनुमति देता है। मुझे हाल ही में एक nHibernate उत्पन्न क्वेरी प्रदान करने के लिए ऐसा करना पड़ा, जिसमें एक उपयोगी सूचकांक के साथ SELECT में बहुत सारे कॉलम थे।


3

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

आपके उदाहरण को ध्यान में रखते हुए:

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)

यदि आपकी क्वेरी इस तरह दिखती है तो यह सूचकांक सबसे अच्छा है:

SELECT col2, col3
  FROM MyTable
 WHERE col1 = ...

निश्चित रूप से आपको कॉलम नहीं रखना चाहिए INCLUDEयदि आप उन्हें मुख्य भाग में होने से अतिरिक्त लाभ प्राप्त कर सकते हैं। निम्नलिखित दोनों प्रश्न वास्तव col2में सूचकांक की कुंजी में कॉलम को पसंद करेंगे ।

SELECT col2, col3
  FROM MyTable
 WHERE col1 = ...
   AND col2 = ...
SELECT TOP 1 col2, col3
  FROM MyTable
 WHERE col1 = ...
 ORDER BY col2

मान लेते हैं कि ऐसा नहीं है और हमारे पास col2हैINCLUDE खंड है, क्योंकि सिर्फ सूचकांक के पेड़ भाग में यह होने का कोई लाभ नहीं।

कुछ साल तेजी से आगे बढ़ा।

आपको इस क्वेरी को ट्यून करने की आवश्यकता है:

SELECT TOP 1 col2
  FROM MyTable
 WHERE col1 = ...
 ORDER BY another_col

उस क्वेरी को ऑप्टिमाइज़ करने के लिए, निम्न सूचकांक बहुत अच्छा होगा:

CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2)

यदि आप जाँचते हैं कि आपके पास उस तालिका में पहले से क्या सूचकांक हैं, तो आपका पिछला सूचकांक अभी भी हो सकता है:

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)

अब आप जानते हैं कि Col2और Col3इंडेक्स ट्री का हिस्सा नहीं हैं और इस प्रकार रीड इंडेक्स को सीमित करने के लिए उपयोग नहीं किया जाता है और न ही पंक्तियों को ऑर्डर करने के लिए। another_columnसूचकांक के कुंजी-भाग के अंत में जोड़ने के लिए सुरक्षित है (बाद में col1)। कुछ भी तोड़ने का जोखिम बहुत कम है:

DROP INDEX idx1 ON MyTable;
CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2, Col3);

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

यदि आपके पास एक सूचकांक है INCLUDE, तो आप यह नहीं जान सकते कि आप किन प्रश्नों को another_colसही जोड़कर तोड़ेंगे Col1

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)

यदि आप और के another_colबीच में क्या होता है ? क्या अन्य प्रश्नों का सामना करना पड़ेगा?Col1Col2

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

तुम्हारे प्रश्न का उत्तर देने के लिए:

INCLUDE क्लॉज़ के साथ या उसके बिना एक कवरिंग इंडेक्स बनाने के लिए आप क्या दिशा-निर्देश तय करेंगे?

यदि आप एकमात्र स्तंभ के लिए इंडेक्स में एक कॉलम जोड़ते हैं, तो उस कॉलम को टेबल पर आए बिना इंडेक्स में उपलब्ध किया जा सकता है, इसे अंदर डालें INCLUDE खंड ।

यदि स्तंभ को इंडेक्स की में जोड़ना अतिरिक्त लाभ (जैसे के लिए) लाता है order by या क्योंकि यह रीड इंडेक्स रेंज को कम कर सकता है) तो इसे कुंजी में जोड़ें।

आप इसके बारे में एक लंबी चर्चा यहाँ पढ़ सकते हैं:

https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes


2

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

दूसरी ओर, StoreID पर सूचकांक को परिभाषित करते हुए और LastName, FirstName सहित, DOB कॉलम आपको सार में दो व्यू-इंडेक्स की भविष्यवाणी करने देता है और फिर किसी भी शामिल कॉलम पर विधेय की तलाश करता है। जब तक यह StoreID के साथ शुरू होता है तब तक आपको सभी संभावित खोज क्रमों को कवर करने देगा।

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