कॉलम आकार बढ़ने के बाद एक इंडेक्स बनाने में अधिक समय क्यों लग रहा है?


18

हमारे विक्रेता ने पूरे डेटाबेस में लगभग हर कॉलम पर कॉलम की चौड़ाई बदल दी। डेटाबेस लगभग 7TB, 9000+ टेबल है। हम एक मेज पर एक इंडेक्स बनाने की कोशिश कर रहे हैं जिसमें 5.5 बिलियन पंक्तियाँ हैं। वेंडर के अपग्रेड से पहले हम 2 घंटे में इंडेक्स बना सकते हैं। अब तो दिन लग जाते हैं। उन्होंने जो भी किया है, वह किसी भी varchar (xx) के आकार को varchar (256) तक बढ़ाता है। इसलिए अधिकांश स्तंभों में वर्चर (18) या वर्चर (75), आदि होते थे।

वैसे भी प्राथमिक कुंजी में 6 कॉलम होते हैं जो संयुक्त चौड़ाई 126 वर्ण थे। नवीनीकरण के बाद, प्राथमिक कुंजी 1283 वर्ण है जो 900 वर्णों की SQL सर्वर सीमा का उल्लंघन करती है। संपूर्ण तालिका स्तंभ की चौड़ाई कुल संयुक्त varchar संख्या 1049 से कुल संयुक्त varchar गिनती 4009 तक गई।

डेटा में कोई वृद्धि नहीं हुई है, सभी स्तंभ चौड़ाई बढ़ने से पहले तालिका ने कोई "स्थान" नहीं लिया है, लेकिन एक इंडेक्स के रूप में कुछ सरल बनाने के लिए प्रदर्शन अब अनुचित समय ले रहा है।

क्या कोई यह बता सकता है कि जब केवल एक ही चीज़ कॉलम का आकार बढ़ा रही थी, तो इसे बनाने और अनुक्रमित करने में इतना अधिक समय क्यों लग रहा है?

जिस इंडेक्स को बनाने की हम कोशिश कर रहे हैं वह नॉन-क्लस्टर है क्योंकि पीके क्लस्टर्ड इंडेक्स है। सूचकांक बनाने के कई प्रयासों के बाद, हमने हार मान ली। मुझे लगता है कि यह बिना पूरा हुए 4 या 5 दिन चला।

मैंने एक फाइल सिस्टम स्नैपशॉट लेकर गैर-उत्पादन परिवेश में यह कोशिश की और डेटाबेस को एक शांत सर्वर पर लाया।

जवाबों:


12

रेमुस ने सहायक रूप से बताया है कि VARCHARस्तंभ की अधिकतम लंबाई अनुमानित पंक्ति आकार को प्रभावित करती है और इसलिए SQL सर्वर द्वारा प्रदान की जाने वाली मेमोरी अनुदान।

मैंने उसके उत्तर के भाग से "इस पर चीजों को कैस्केड" करने के लिए थोड़ा और शोध करने की कोशिश की। मेरे पास पूर्ण या संक्षिप्त स्पष्टीकरण नहीं है, लेकिन यहां वही है जो मैंने पाया है।

रेप्रो स्क्रिप्ट

मैंने एक पूरी स्क्रिप्ट बनाई जो एक नकली डेटा सेट उत्पन्न करती है जिस पर सूचकांक निर्माण VARCHAR(256)संस्करण के लिए मेरी मशीन पर लगभग 10x लेता है । उपयोग किए गए डेटा बिल्कुल वैसा ही है, लेकिन पहले मेज की वास्तविक अधिकतम लंबाई का उपयोग करता है 18, 75, 9, 15, 123, और 5, सभी स्तंभों की एक अधिकतम लंबाई का उपयोग करते हुए 256दूसरी तालिका में।


मूल सारणी की कुंजी लगाना

यहां हम देखते हैं कि मूल क्वेरी लगभग 20 सेकंड में पूरी होती है और तार्किक ~1.5GBरीड्स (195K पेज, 8K प्रति पेज) के टेबल साइज के बराबर होते हैं ।

-- CPU time = 37674 ms,  elapsed time = 19206 ms.
-- Table 'testVarchar'. Scan count 9, logical reads 194490, physical reads 0
CREATE CLUSTERED INDEX IX_testVarchar
ON dbo.testVarchar (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


VARCHAR (256) तालिका की कुंजी लगाना

के लिए VARCHAR(256)मेज, हम देखते हैं कि बीता हुआ समय नाटकीय रूप से वृद्धि हुई है।

दिलचस्प है, न तो सीपीयू समय और न ही तार्किक रीड बढ़ता है। इससे यह समझ में आता है कि तालिका में ठीक वैसा ही डेटा है, लेकिन यह स्पष्ट नहीं करता है कि बीता हुआ समय इतना धीमा क्यों है।

-- CPU time = 33212 ms,  elapsed time = 263134 ms.
-- Table 'testVarchar256'. Scan count 9, logical reads 194491
CREATE CLUSTERED INDEX IX_testVarchar256
ON dbo.testVarchar256 (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


I / O और प्रतीक्षा आँकड़े: मूल

यदि हम थोड़ा और अधिक विवरण कैप्चर करते हैं ( p_perfMon, एक प्रक्रिया जो मैंने लिखी है ) का उपयोग करके , हम देख सकते हैं कि I / O का अधिकांश भाग LOGफ़ाइल पर किया जाता है । हम वास्तविक ROWS(मुख्य डेटा फ़ाइल) पर I / O की अपेक्षाकृत मामूली मात्रा देखते हैं , और प्राथमिक प्रतीक्षा प्रकार है LATCH_EX, जो स्मृति पृष्ठ विवाद का संकेत देता है।

हम यह भी देख सकते हैं कि मेरी कताई डिस्क "बुरा" और "आश्चर्यजनक बुरा" के बीच कहीं है, पॉल रैंडल के अनुसार :)

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


I / O और प्रतीक्षा आँकड़े: VARCHAR (256)

के लिए VARCHAR(256)संस्करण, आई / ओ और इंतजार आँकड़े पूरी तरह से अलग हैं! यहाँ हम डेटा फ़ाइल ( ROWS) पर I / O में भारी वृद्धि देखते हैं , और स्टाल अब पॉल रैंडल को केवल "WOW!" कहते हैं।

यह आश्चर्य की बात नहीं है कि # 1 प्रतीक्षा प्रकार अब है IO_COMPLETION। लेकिन इतना I / O क्यों उत्पन्न होता है?

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


वास्तविक क्वेरी योजना: VARCHAR (256)

क्वेरी योजना से, हम देख सकते हैं कि Sortऑपरेटर के पास VARCHAR(256)क्वेरी के संस्करण में एक पुनरावर्ती स्पिल (5 स्तर गहरा!) है । (मूल संस्करण में कोई स्पिल बिल्कुल नहीं है।)

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


लाइव क्वेरी प्रगति: VARCHAR (256)

हम SQL 2014+ में लाइव क्वेरी प्रगति देखने के लिए sysinos_exec_query_profiles का उपयोग कर सकते हैं । मूल संस्करण में, पूरी Table Scanऔर Sortकिसी भी फैल (बिना कार्रवाई की जाती है spill_page_countअवशेष 0भर)।

में VARCHAR(256)संस्करण, तथापि, हम देख सकते हैं कि पेज फैल जल्दी के लिए जमा Sortऑपरेटर। यहां क्वेरी पूरा होने से ठीक पहले क्वेरी प्रगति का एक स्नैपशॉट है। यहां डेटा सभी थ्रेड्स में एकत्रित है।

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

यदि मैं व्यक्तिगत रूप से प्रत्येक थ्रेड में खुदाई करता हूं, तो मैं देखता हूं कि 2 थ्रेड्स लगभग 5 सेकंड (@ 20 सेकंड कुल मिलाकर, टेबल स्कैन पर खर्च किए गए 15 सेकंड के बाद) को पूरा करते हैं। यदि सभी धागे इस दर पर आगे बढ़ते हैं, तो VARCHAR(256)सूचकांक निर्माण मूल तालिका के समान समय में पूरा हो जाता।

हालांकि, शेष 6 धागे बहुत धीमी दर पर प्रगति करते हैं। यह उस तरीके के कारण हो सकता है जिस तरह से मेमोरी आवंटित की जाती है और जिस तरह से थ्रेड्स I / O द्वारा पकड़े जा रहे हैं, क्योंकि वे डेटा स्पिल कर रहे हैं। हालांकि मुझे यकीन नहीं है।

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


तुम क्या कर सकते हो?

ऐसी कई चीजें हैं जिन पर आप प्रयास करने पर विचार कर सकते हैं:

  • विक्रेता के साथ पिछले संस्करण में वापस आने के लिए काम करें। यदि यह संभव नहीं है, तो विक्रेता को बताएं कि आप इस बदलाव से खुश नहीं हैं ताकि वे इसे भविष्य में जारी करने पर विचार कर सकें।
  • जब आपके सूचकांक जोड़ने, प्रयोग करने पर विचार OPTION (MAXDOP X)जहां Xआपके वर्तमान सर्वर स्तरीय सेटिंग की तुलना में कम संख्या है। जब मैंने OPTION (MAXDOP 2)अपनी मशीन पर इस विशिष्ट डेटा सेट का उपयोग किया , तो VARCHAR(256)संस्करण पूर्ण हुआ 25 seconds(8 थ्रेड के साथ 3-4 मिनट की तुलना में!)। यह संभव है कि उच्च बर्बरता से फैलने वाला व्यवहार तेज हो।
  • यदि अतिरिक्त हार्डवेयर निवेश एक संभावना है, तो अपने सिस्टम पर I / O (संभावित अड़चन) को प्रोफ़ाइल करें और फैल द्वारा किए गए I / O की विलंबता को कम करने के लिए SSD का उपयोग करने पर विचार करें।


आगे की पढाई

पॉल व्हाइट के पास SQL Server के इंटर्नल्स पर एक अच्छा ब्लॉग पोस्ट है जो रुचि का हो सकता है। यह स्पेलिंग, थ्रेड स्क्यू और समानांतर प्रकार के लिए मेमोरी आवंटन के बारे में थोड़ी बात करता है।


11

दो मामलों के बीच मध्यवर्ती सॉर्ट तालिका अलग-अलग अनुमानित की जाएगी। इससे अलग-अलग मेमोरी अनुदान अनुरोध ( VARCHAR(256)बड़े होंगे) और 'आदर्श' अनुरोध के साथ तुलना में बहुत कम वास्तविक अनुदान, प्रतिशत वार की संभावना होगी। मुझे लगता है कि यह छँटाई के दौरान फैलता है।

ज्योफ से स्क्रिप्ट का परीक्षण (केवल 100k पंक्तियों पर) मैं स्पष्ट रूप से अनुमानित अनुमानित आकार के आकार (141B बनाम 789B) में अंतर देख सकता हूं। इस पर चीजों से झरना।


8
मुझे यकीन है कि पॉल कॉल स्टैक्स सहित एक अधिक गहन और पूर्ण उत्तर साबित करेगा, जिसका उपयोग देव टीम द्वारा शिक्षण सामग्री के रूप में किया जाएगा। फिर से ...
रेमुस रुसानु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.