अपनी पिछली पोस्ट में, मैंने सीएक्सपैकेट प्रतीक्षा और समानता को रोकने या सीमित करने के तरीकों पर चर्चा की। मैंने यह भी बताया कि समानांतर ऑपरेशन में कंट्रोल थ्रेड हमेशा एक CXPACKET प्रतीक्षा कैसे पंजीकृत करता है, और कभी-कभी गैर-नियंत्रण थ्रेड भी CXPACKET प्रतीक्षा को पंजीकृत कर सकते हैं। ऐसा तब हो सकता है जब किसी एक थ्रेड को किसी संसाधन की प्रतीक्षा में अवरुद्ध कर दिया जाता है (इसलिए अन्य सभी थ्रेड इसके पहले समाप्त हो जाते हैं और CXPACKET भी प्रतीक्षा करते हैं), या यदि कार्डिनैलिटी अनुमान गलत हैं। इस पोस्ट में मैं बाद का पता लगाना चाहता हूं।
जब कार्डिनैलिटी अनुमान गलत होते हैं, तो क्वेरी कार्य करने वाले समानांतर थ्रेड्स को काम करने के लिए असमान मात्रा में दिया जाता है। विशिष्ट मामला वह है जहां एक धागे को सभी काम दिए जाते हैं, या अन्य धागे की तुलना में अधिक काम किया जाता है। इसका मतलब यह है कि वे धागे जो अपनी पंक्तियों को संसाधित करना समाप्त करते हैं (यदि उन्हें भी दिया गया था) सबसे धीमे धागे से पहले एक CXPACKET पंजीकृत करें जब तक कि वे सबसे धीमे धागे के खत्म होने तक समाप्त न हो जाएं। इस समस्या के कारण CXPACKET वेटिंग में एक विस्फोट हो सकता है और इसे आमतौर पर स्क्यूड पैरेललिज़्म कहा जाता है। , क्योंकि समानांतर धागों के बीच कार्य का वितरण विषम है, यहाँ तक कि नहीं भी।
ध्यान दें कि SQL Server 2016 SP2 और SQL Server 2017 RTM CU3 में, उपभोक्ता थ्रेड्स अब पंजीकृत नहीं हैं CXPACKET प्रतीक्षा करता है। वे CXCONSUMER प्रतीक्षा को पंजीकृत करते हैं, जो सौम्य हैं और जिन्हें अनदेखा किया जा सकता है। यह उत्पन्न होने वाले CXPACKET प्रतीक्षा की संख्या को कम करने के लिए है, और शेष लोगों के कार्रवाई योग्य होने की अधिक संभावना है।
तिरछी समानता का उदाहरण
ऐसे मामलों की पहचान कैसे करें, यह दिखाने के लिए मैं एक काल्पनिक उदाहरण के माध्यम से चलूंगा।
सबसे पहले, मैं अद्यतन आंकड़े में पंक्तियों और पृष्ठों की संख्या को मैन्युअल रूप से सेट करके, एक ऐसा परिदृश्य बनाऊंगा जहां एक तालिका में बेतहाशा गलत आंकड़े हों कथन (उत्पादन में ऐसा न करें!):
उपयोग [मास्टर]; GO यदि DB_ID (N'ExecutionMemory') NULLBEGIN ALTER DATABASE नहीं है [ExecutionMemory] ROLLBACK IMMEDIATE के साथ SINGLE_USER सेट करें; ड्रॉप डेटाबेस [एक्ज़ीक्यूशनमेमोरी];एंडगो क्रिएट डेटाबेस [एक्ज़ीक्यूशनमेमोरी];गौस [एक्ज़ीक्यूशनमेमरी];गो क्रिएट टेबल डीबीओ। प्राथमिक कुंजी क्लस्टर ([RowID]));डीबीओ में प्रवेश करें। ] - [t1]। [संख्या]% 6 ELSE [t1]। [संख्या] END, 'टेस्ट' + कास्ट ([t1]। [संख्या]% 2 AS VARCHAR(11)) [मास्टर] से। [dbo] [spt_values] AS [t1] जहां [t1]। [टाइप] ='P'; GO UPDATE STATISTICS dbo।[Test] ([PK_Test]) ROWCOUNT के साथ =10000000, PAGECOUNT =1000000;GO
तो मेरी तालिका में केवल कुछ हज़ार पंक्तियाँ हैं, लेकिन मैंने इसे 10 मिलियन पंक्तियों में बना दिया है।
अब मैं शीर्ष 500 पंक्तियों का चयन करने के लिए एक काल्पनिक क्वेरी बनाऊंगा, जो समानांतर चलेगी क्योंकि यह सोचता है कि स्कैन करने के लिए लाखों पंक्तियाँ हैं।
उपयोग [एक्ज़ीक्यूशनमेमोरी];जाओ सेट पर NOCOUNT;GO DECLARE @CurrentValue NVARCHAR (100); जबकि (1=1)शीर्ष (500) @CurrentValue =[CurrentValue]dbo से चुनें। [टेस्ट] NEWID द्वारा आदेश() DESC;GO
और उस रनिंग को सेट करें।
CXPACKET वेटिंग देखना
अब मैं sys.dm_os_waiting_tasks को देखने के लिए एक साधारण स्क्रिप्ट का उपयोग करके होने वाली CXPACKET प्रतीक्षा को देख सकता हूं डीएमवी:
चुनें [owt]।[session_id], [owt]।[exec_context_id], [owt]। ], [एर]।[डेटाबेस_आईडी], [ईक्यूपी]। sys.dm_exec_requests [er] पर [es]। plan_handle]) [eqp]कहां [es]। [is_user_process] =1 [owt] द्वारा आदेश। [session_id], [owt]।यदि मैं इसे कुछ बार निष्पादित करता हूं, तो अंततः मुझे कुछ परिणाम विषम समानता दिखाते हुए दिखाई देते हैं (मैंने क्वेरी प्लान हैंडल लिंक को हटा दिया और स्पष्टता के लिए संसाधन विवरण को कम कर दिया, और यदि आप चाहते हैं तो मैंने SQL टेक्स्ट को हथियाने के लिए कोड में नोटिस किया है। भी):
session_id | <वें शैली="फ़ॉन्ट-आकार:11px!महत्वपूर्ण">exec_context_idwait_duration_ms | <वें शैली="फ़ॉन्ट-आकार:11px!महत्वपूर्ण">प्रतीक्षा_प्रकारblocking_session_id | <वें शैली="फ़ॉन्ट-आकार:11px!महत्वपूर्ण">संसाधन_विवरण <वें शैली="फ़ॉन्ट-आकार:11px!महत्वपूर्ण">डेटाबेस_आईडी||||
---|---|---|---|---|---|---|
56 | 0 | 1 | CXPACKET | NULL | exchangeEvent | 13 |
56 | 1 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
56 | 3 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
56 | 4 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
56 | 5 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
56 | 6 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
56 | 7 | 1 | CXPACKET | 56 | exchangeEvent | 13 |
कार्य में विषम समानता दिखाने वाले परिणाम
नियंत्रण धागा वह है जिसमें exec_context_id . है 0 पर सेट। अन्य समानांतर धागे वे हैं जिनमें exec_context_id . है 0 से अधिक है, और वे सभी एक के अलावा CXPACKET प्रतीक्षा दिखा रहे हैं (ध्यान दें कि exec_context_id = 2
सूची से गायब है)। आप देखेंगे कि वे सभी अपना session_id सूचीबद्ध करते हैं जैसा कि उन्हें ब्लॉक कर रहा है, और यह सही है क्योंकि सभी थ्रेड अपने स्वयं के session_id से दूसरे थ्रेड की प्रतीक्षा कर रहे हैं पूर्ण करना। डेटाबेस_आईडी वह डेटाबेस है जिसके संदर्भ में क्वेरी निष्पादित की जा रही है, जरूरी नहीं कि वह डेटाबेस जहां समस्या है, लेकिन यह आमतौर पर तब तक होता है जब तक कि क्वेरी किसी भिन्न डेटाबेस में निष्पादित करने के लिए तीन-भाग के नामकरण का उपयोग नहीं कर रही हो।
कार्डिनैलिटी अनुमान समस्या देखना
query_plan . के साथ क्वेरी आउटपुट में कॉलम (जिसे मैंने स्पष्टता के लिए हटा दिया), आप ग्राफिकल प्लान लाने के लिए उस पर क्लिक कर सकते हैं और फिर राइट-क्लिक कर सकते हैं और SQL सेंट्री प्लान एक्सप्लोरर के साथ व्यू का चयन कर सकते हैं। यह नीचे दिखाया गया है:
मैं तुरंत देख सकता हूं कि कार्डिनैलिटी अनुमान की समस्या है, क्योंकि 10,000,000 अनुमानित (अनुमानित) पंक्तियों की तुलना में क्लस्टर्ड इंडेक्स स्कैन के लिए वास्तविक पंक्तियाँ केवल 2,048 हैं।
यदि मैं स्क्रॉल करता हूँ, तो मैं उन समानांतर धागों में पंक्तियों का वितरण देख सकता हूँ जिनका उपयोग किया गया था:
देखो और देखो, योजना के समानांतर भाग के दौरान केवल एक धागा ही कोई काम कर रहा था - वह जो sys.dm_os_waiting_tasks में दिखाई नहीं दिया। ऊपर आउटपुट।
इस मामले में, तालिका के लिए आंकड़ों को अद्यतन करना ठीक है।
मेरे काल्पनिक उदाहरण में जो काम नहीं करेगा, क्योंकि तालिका में कोई संशोधन नहीं किया गया है, इसलिए मैं अद्यतन सांख्यिकी को छोड़कर, सेट अप स्क्रिप्ट को फिर से चलाऊंगा बयान।
क्वेरी योजना तब बन जाती है:
जहां कोई कार्डिनैलिटी समस्या नहीं है और कोई समानता नहीं है - समस्या हल हो गई है!
सारांश
यदि आप देखते हैं कि CXPACKET प्रतीक्षा कर रहा है, तो ऊपर वर्णित विधि का उपयोग करके विषम समानता की जांच करना आसान है। मैंने जितने भी मामले देखे हैं, वे किसी न किसी प्रकार के कार्डिनैलिटी अनुमान के मुद्दों के कारण हैं, और अक्सर यह केवल आंकड़ों को अद्यतन करने का मामला है।
जहां तक सामान्य प्रतीक्षा आंकड़ों का संबंध है, आप प्रदर्शन समस्या निवारण के लिए उनका उपयोग करने के बारे में अधिक जानकारी यहां प्राप्त कर सकते हैं:
- मेरी SQLskills ब्लॉग पोस्ट श्रृंखला, प्रतीक्षा आँकड़ों से शुरू होती है, या कृपया मुझे बताएं कि यह कहाँ दर्द होता है
- मेरे प्रतीक्षा प्रकार और कुंडी कक्षा पुस्तकालय यहाँ
- मेरा प्लूरलसाइट ऑनलाइन प्रशिक्षण पाठ्यक्रम SQL सर्वर:प्रतीक्षा सांख्यिकी का उपयोग करके प्रदर्शन समस्या निवारण
- एसक्यूएल संतरी
अगली बार तक, समस्या निवारण के लिए शुभकामनाएं!