पीके इंडेक्स में कॉलम का क्रम मायने रखता है?


33

मेरे पास एक ही मूल स्ट्रचर के साथ कुछ बहुत बड़ी टेबल हैं। हर एक में एक कॉलम RowNumber (bigint)और DataDate (date)कॉलम है। हर रात SQLBulkImport का उपयोग करके डेटा लोड किया जाता है, और कोई "नया" डेटा कभी भी लोड नहीं किया जाता है - इसका एक ऐतिहासिक रिकॉर्ड (SQL मानक, एंटरप्राइज़ नहीं, इसलिए कोई विभाजन नहीं)।

क्योंकि प्रत्येक बिट डेटा को अन्य प्रणालियों में वापस बांधने की आवश्यकता होती है, और प्रत्येक RowNumber/DataDateसंयोजन अद्वितीय है, यही मेरी प्राथमिक कुंजी है।

मैंने देखा कि जिस तरह से मैंने SSMS टेबल डिज़ाइनर में PK को परिभाषित किया है, RowNumberवह पहले और DataDateदूसरे स्थान पर है।

मैं यह भी नोटिस करता हूं कि मेरा विखंडन हमेशा बहुत उच्च ~ 99% है।

अब, क्योंकि प्रत्येक DataDateकेवल एक बार दिखाई देता है, मैं उम्मीद करता हूं कि अनुक्रमणिका को प्रत्येक दिन केवल पृष्ठों में जोड़ना होगा, लेकिन मुझे आश्चर्य है कि क्या यह वास्तव में RowNumberपहले के आधार पर अनुक्रमण कर रहा है, और इसलिए बाकी सब कुछ आसपास स्थानांतरित करना है?


Rownumberएक पहचान स्तंभ नहीं है, यह एक बाहरी प्रणाली (दुख की बात) द्वारा उत्पन्न एक int है। यह प्रत्येक की शुरुआत में रहता है DataDate

उदाहरण डेटा

RowNumber | DataDate | a | b | c..... 
   1      |2013-08-01| x | y | z 
   2      |2013-08-01| x | y | z 
...
   1      |2013-08-02| x | y | z 
   2      |2013-08-02| x | y | z 
...

डेटा लोड किया जा रहा है RowNumber, DataDateप्रति लोड एक ।

आयात प्रक्रिया bcp है - मैंने एक अस्थायी तालिका में लोड करने की कोशिश की है और फिर वहां से क्रम में चयन किया है ( ORDER BY RowNumber, DataDate) लेकिन फिर भी उच्च विखंडन निकलता है।

जवाबों:


50

पीके इंडेक्स में कॉलम का क्रम मायने रखता है?

हाँ यह करता है।

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

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

की एक प्राथमिक प्राथमिक कुंजी के साथ (RowNumber, DataDate), पंक्तियों को तार्किक रूप से पहले RowNumberऔर बाद में क्रमबद्ध किया जाता है DataDate- इसलिए सभी पंक्तियों को जहां RowNumber = 1तार्किक रूप से समूहीकृत किया जाता है, फिर पंक्तियों को कहां RowNumber = 2और कहां से जोड़ा जाता है ।

जब आप नया डेटा ( RowNumbers1 से n के साथ) जोड़ते हैं, तो नई पंक्तियाँ तार्किक रूप से मौजूदा पृष्ठों के अंदर होती हैं, इसलिए SQL सर्वर को कमरे बनाने के लिए बहुत सारे कार्य विभाजन पृष्ठ करने की संभावना होगी। यह सभी गतिविधि बिना किसी लाभ के बहुत सारे अतिरिक्त कार्य (परिवर्तनों को लॉग इन करने सहित) उत्पन्न करती है।

स्प्लिट पेज भी लगभग 50% खाली होने लगते हैं, इसलिए अधिक बंटवारे के परिणामस्वरूप कम पेज घनत्व (प्रति पृष्ठ इष्टतम से कम पंक्तियाँ) हो सकता है। न केवल डिस्क से पढ़ने के लिए यह बुरी खबर है (कम घनत्व = पढ़ने के लिए अधिक पृष्ठ), कम घनत्व वाले पृष्ठ भी कैश होने पर स्मृति में अधिक कमरा लेते हैं।

क्लस्टर किए गए इंडेक्स को (DataDate, RowNumber) में बदलने का मतलब है कि नए डेटा ( DataDatesवर्तमान में संग्रहीत की तुलना में अधिक ), ताजा पृष्ठों पर क्लस्टर किए गए इंडेक्स के तार्किक अंत में संलग्न है। इससे बंटवारे के अनावश्यक ओवरहेड्स को हटा दिया जाएगा और परिणाम तेजी से लोड हो जाएगा। कम खंडित डेटा का मतलब यह भी है कि रीड-फॉरवर्ड एक्टिविटी (डिस्क से पृष्ठों को पढ़ना, इससे पहले कि वे इन-प्रोग्रेस क्वेरी के लिए आवश्यक हों) अधिक कुशल हो सकते हैं।

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

जब नया डेटा आयात किया जाता है bcp, तो आप उच्च प्रदर्शन प्राप्त कर सकते हैं यदि आयात फ़ाइल के डेटा को क्लस्टर इंडेक्स कीज़ (आदर्श रूप से (DataDate, RowNumber) द्वारा सॉर्ट किया जाता है और आप bcpविकल्प निर्दिष्ट करते हैं :

-h "ORDER(DataDate,RowNumber), TABLOCK"

सर्वश्रेष्ठ डेटा लोडिंग प्रदर्शन के लिए, आप न्यूनतम लॉग-इन आवेषण प्राप्त करने का प्रयास कर सकते हैं। अधिक जानकारी के लिए देखें:


4
एक उत्कृष्ट उत्तर - मुझे अब पता है कि मुझे क्या करना चाहिए और क्यों करना चाहिए। मैंने ऐसा सोचा था, लेकिन ऐसा नहीं हुआ! धन्यवाद।
BlueChippy

परीक्षण के लिए मेरे स्थानीय SQL सर्वर में DB प्राप्त करने के लिए एक LOOOOONG लिया गया: परिवर्तन से पहले सूचकांक लोड में 45 मिनट लगते हैं ... बाद में, यह सिर्फ 5 लिया गया !!!
BlueChippy

13

हाँ, आदेश महत्वपूर्ण है। मुझे अत्यधिक संदेह है कि आप कभी भी RowNumber (जैसे WHERE RowNumber=1) से क्वेरी करते हैं । अत्यधिक समय श्रृंखला की तारीख ( WHERE DataDate BEWEEN @start AND @end) द्वारा क्वेरी की जाती है और इस तरह के प्रश्नों के लिए एक संकुल संगठन की आवश्यकता होगी DataDate

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


मेरे पास DataDate पर एक नॉन-क्लस्टर्ड इंडेक्स (es) भी है, जैसा कि आप कहते हैं कि अक्सर WHEREप्रश्नों में क्लॉज होता है।
BlueChippy

1
यदि स्तंभों का ORDER महत्वपूर्ण है, तो क्या मेरे आई / ओ में वृद्धि के आदेश का प्रभाव कम होगा? मेरा विचार है कि यह रोवनंबर द्वारा ऑर्डर कर रहा है और इसलिए हर बार इंडेक्स पर बहुत काम करना है, जबकि यह डेटाडेट पर आधारित होना चाहिए?
BlueChippy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.