रेमुस ने सहायक रूप से बताया है कि 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 के इंटर्नल्स पर एक अच्छा ब्लॉग पोस्ट है जो रुचि का हो सकता है। यह स्पेलिंग, थ्रेड स्क्यू और समानांतर प्रकार के लिए मेमोरी आवंटन के बारे में थोड़ी बात करता है।