प्राथमिक कुंजी को गैर-संकुलित कब घोषित किया जाना चाहिए?


169

पहले पूछे गए एक अन्य प्रश्न के लिए एक परीक्षण डेटाबेस बनाते समय, मुझे एक प्राथमिक कुंजी के बारे में याद था जिसे घोषित किया जा सकता था NONCLUSTERED

आप NONCLUSTEREDप्राथमिक कुंजी के विपरीत प्राथमिक कुंजी का उपयोग कब करेंगे CLUSTERED?

अग्रिम में धन्यवाद

जवाबों:


187

सवाल यह नहीं है कि 'पीके को NC कब होना चाहिए', बल्कि आपको यह पूछना चाहिए कि 'क्लस्टर इंडेक्स के लिए उचित कुंजी क्या है'?

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

पहेली का एक और टुकड़ा यह है कि सूचकांक का उपयोग कैसे किया जा सकता है ? तीन विशिष्ट पैटर्न हैं:

  • जांच करता है, जब सूचकांक में एकल कुंजी मूल्य की तलाश होती है
  • श्रेणी स्कैन, जब कुंजी मानों की एक श्रृंखला पुनर्प्राप्त की जाती है
  • आवश्यकताओं द्वारा आदेश, जब एक सूचकांक w / o द्वारा स्टॉप-एंड-गो सॉर्ट की आवश्यकता के ऑर्डर को संतुष्ट कर सकता है

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

फिर भी एक अन्य कारक यह है कि संकुल सूचकांक कुंजी सभी गैर-संकुलित सूचकांकों द्वारा उपयोग की जाने वाली लुकअप कुंजी है और इसलिए एक विस्तृत क्लस्टर इंडेक्स कुंजी एक तरंग प्रभाव पैदा करती है और सभी गैर-क्लस्टर सूचकांकों और विस्तृत सूचकांकों को अधिक पृष्ठ, अधिक I / O , अधिक स्मृति, कम अच्छाई।

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

और एक अच्छा क्लस्टर इंडेक्स बेतरतीब ढंग से नहीं बढ़ता है (प्रत्येक नए सम्मिलित कुंजी मूल्य पूर्ववर्ती मूल्य से बड़ा है) के रूप में पेज विभाजन और विखंडन ( FILLFACTORएस के साथ खिलवाड़ के बिना) से बचने के लिए ।

तो अब जब हम जानते हैं कि एक अच्छा क्लस्टर इंडेक्स कुंजी क्या है, तो प्राथमिक कुंजी (जो कि तार्किक संपत्ति का डेटा मॉडलिंग करती है) क्या आवश्यकताओं से मेल खाती है? यदि हाँ, तो पीके का क्लस्टर किया जाना चाहिए। यदि नहीं, तो पीके गैर-संकुल होना चाहिए।

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

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


1
"आवश्यकताओं द्वारा आदेश क्या होता है, जब एक सूचकांक w / o द्वारा एक क्रम को संतुष्ट कर सकता है, यहां एक स्टॉप-एंड-गो सॉर्ट की आवश्यकता होती है"?
माइक शेरिल 'कैट रिकॉल'

2
@RemusRusanu। +1 बहुत उपयोगी जवाब। उदाहरण के संबंध में एक प्रश्न (state, id)। इस उदाहरण में "अच्छा संकुल सूचकांक क्रम में नहीं यादृच्छिक रूप से बढ़ता है" आवश्यकता पूरी नहीं होगी, है ना? तो क्या हम इसे अच्छा क्लस्टर इंडेक्स मान सकते हैं?
लिजो

26

संकुल अनुक्रमित का उपयोग करने का मूल कारण विकिपीडिया पर बताया गया है :

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

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

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

इसके अलावा, यहाँ Clustered vs Nonclustered Indexes पर एक अच्छा लेख है, Clustered Indexes को SQL Server 6.5 में सम्मिलित प्रदर्शन समस्याओं का कारण बना (जो कम से कम उम्मीद है कि हम में से अधिकांश के लिए प्रासंगिक नहीं है)।

यदि आप IDENTITY स्तंभ पर एक संकुल सूचकांक रखते हैं, तो आपका सभी आवेषण तालिका के अंतिम पृष्ठ पर होगा - और यह पृष्ठ प्रत्येक IDENTITY की अवधि के लिए लॉक है। कोई बड़ी बात नहीं ... जब तक आपके पास 5000 लोग नहीं होंगे जो सभी अंतिम पृष्ठ चाहते हैं। तब आपके पास उस पृष्ठ के लिए बहुत अधिक विवाद है

ध्यान दें कि बाद के संस्करणों में ऐसा नहीं है।


3
FIY, आपने SQL सर्वर 6.5: dba.stackexchange.com/questions/1584/…
gbn

15

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


1
हालांकि मैं संकुल कुंजी के लिए यूयूआईडी से बचने की कोशिश करता हूं, मेरा मानना ​​है कि ऊपर दिया गया तर्क अधूरा हो सकता है। SQL सर्वर आवश्यक रूप से सही स्थिति में डालने के लिए पंक्तियों को फेरबदल नहीं करता है (यदि आपका मतलब है "निचले और उच्च मूल्य के बीच")। ट्रिलियन पंक्ति तालिका के मध्य में सम्मिलित होने पर विचार करें। अतिरिक्त अप्रत्यक्षता की आवश्यकता है, जो आपके मतलब के हो सकते हैं। एक अनुक्रमिक UNIQUEIDENTIFIERप्रकार भी मौजूद है, और अद्वितीय कुंजी उत्पन्न करने की समान संभावना है, हालांकि यह अभी भी 128 आकार से ग्रस्त है।
चार्ल्स बर्न

7

एक बहुत ही सामान्य उदाहरण:

  • Customerतालिका के साथ CustomerIDके रूप मेंCLUSTERED PRIMARY KEY
  • आदेश तालिका OrderID (PK), CustomerID, OrderDateऔर कुछ अन्य स्तंभों के साथ
  • OrderPositions साथ में OrderPositionID (PK), OrderId, ProductID, Amount, Price ...
  • आपको आदेश तालिकाओं को अनुक्रमित करना होगा

बेशक "यह निर्भर करता है" - लगभग हमेशा की तरह - सही उत्तर है, लेकिन सबसे अधिक एप्लिकेशन (बीआई-रिपोर्ट नहीं) ग्राहक आधारित काम करेगा (जैसे आप वेबसाइट पर ग्राहक 278 के रूप में लॉग इन करते हैं और "मेरे आदेश" पर क्लिक करते हैं) क्लर्क ग्राहक के लिए सभी आदेशों को सूचीबद्ध करता है 4569 या आपका चालान रूटीन ग्राहक के लिए सभी आदेशों को पूरा करेगा 137)।

इस मामले में यह तालिका को क्लस्टर करने के लिए बहुत मायने नहीं रखेगा OrderID। हां, आपके पास SELECT ... WHERE OrderId = ?ऑर्डर विवरण को सूचीबद्ध करने के लिए प्रश्न होंगे , लेकिन यह आमतौर पर लघु और सस्ता (3 रीड्स) इंडेक्स का प्रयास होता है।

दूसरी ओर, यदि आप अपनी Orderतालिका को बंद कर देते हैं CustomerID, तो हर बार जब आप तालिका के लिए क्वेरी करते हैं, तो यह कई महत्वपूर्ण लुकअप नहीं करना होगा CustomerId = ?

CLUSTERED INDEXहमेशा होना चाहिए UNIQUE, अन्यथा एसक्यूएल सर्वर एक अदृश्य (= व्यर्थ) INT स्तंभ जोड़ना होगा UNIQUIFIERuniquiness सुनिश्चित करने के लिए है - और यह तो कुछ यादृच्छिक (डालने के क्रम के आधार पर) सामान वास्तविक (प्रयोग करने योग्य) डेटा जोड़ने के लिए और अधिक समझ बनाने जाएगा।

क्योंकि एक ग्राहक (उम्मीद से) एक से अधिक ऑर्डर करेगा, हमें OrderIDया तो जोड़ना होगा (या यदि आप आमतौर पर इसके लिए सॉर्ट करते हैं) OrderDate(यदि यह एक डेटाटाइम है - अन्यथा ग्राहक प्रति दिन एक ऑर्डर तक सीमित होगा) के साथ CLUSTERED INDEXऔर अंत:

CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)

OrderPositionsटेबल पर भी यही नियम लागू होता है । आमतौर पर सबसे अधिक प्रश्नों विशिष्ट आदेश पर के लिए सभी पदों सूची जाएगा, ताकि आप के साथ पी बनाना चाहिए OrderPositionIDके रूप में NONCLUSTEREDऔर एक UNIQUE CLUSTERED INDEXपर OrderId, OrderPositionID

BTW: यह सही है कि Customerतालिका अपने PK ( CustomerID, द्वारा क्लस्टर की गई है , क्योंकि यह एक "टॉप-लेवल-टेबल" है और एक विशिष्ट एप्लिकेशन में - ज्यादातर ग्राहक द्वारा इसकी पुष्टि की जाएगी।

शुद्ध लुकअप टेबल्स जैसे कि Gendersया InvoiceTypesया PaymentTypeतालिकाओं का एक और उदाहरण है जिसे इसके पीके द्वारा क्लस्टर किया जाना चाहिए (क्योंकि आप आमतौर पर उन पर शामिल होंगे GenderId, InvoiceTypeIdया PaymentTypeId)।


2

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

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

ऐसा तब हो सकता है जब डेटा आमतौर पर एक इंडेक्स का उपयोग करके पुनर्प्राप्त किया जाता है जो अद्वितीय नहीं होता है, जिसमें नल (एक पीके में अनुमति नहीं है), या पीके को द्वितीयक कारण (जैसे प्रतिकृति या ऑडिट ट्रेल रिकॉर्ड पहचान) के लिए जोड़ा गया था।

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