अपनी पिछली पोस्ट में, मैंने LCK_M_XX, ASYNC_NETWORK_IO, और OLEDB वेट्स और उनके प्रति प्रतिक्रिया की चर्चा की थी। इस पोस्ट में मैं प्रतीक्षा सांख्यिकी विषय के साथ जारी रखूंगा और SOS_SCHEDULER_YIELD प्रतीक्षा पर चर्चा करूंगा।
जब सर्वर पर SOS_SCHEDULER_YIELD सबसे अधिक प्रचलित होता है, तो निरंतर, उच्च CPU उपयोग देखना आम बात है। यहां पर प्रतिक्रिया यह है कि सर्वर सीपीयू के दबाव में होना चाहिए, या यह कि स्पिनलॉक समस्या है।
इन दो प्रतिक्रियाओं को समझने के लिए हमें यहां थोड़ी पृष्ठभूमि की आवश्यकता है।
थ्रेड शेड्यूलिंग
SQL सर्वर में थ्रेड शेड्यूलिंग को SQL सर्वर द्वारा ही प्रबंधित किया जाता है, न कि Windows द्वारा (अर्थात यह गैर-प्रीमेप्टिव है)। स्टोरेज इंजन का SQL OS भाग शेड्यूलिंग कार्यक्षमता प्रदान करता है और एक प्रोसेसर (जहां थ्रेड स्थिति चल रही है) पर चलने से वेटर सूची में होने के लिए संसाधन उपलब्ध होने की प्रतीक्षा में थ्रेड्स संक्रमण प्रदान करता है (राज्य निलंबित है) रननेबल पर होने के लिए एक बार संसाधन उपलब्ध हो जाने पर कतार (राज्य चल रहा है) कतार के शीर्ष पर पहुंचने और फिर से प्रोसेसर पर वापस आने की प्रतीक्षा कर रहा है (वापस राज्य में चल रहा है)। मैंने प्रोसेसर, वेटर सूची, और चलने योग्य कतार को एक शेड्यूलर के हिस्से के रूप में पहचानने के लिए कैपिटल किया है।
जब भी किसी थ्रेड को ऐसे संसाधन की आवश्यकता होती है जिसे वह तुरंत प्राप्त नहीं कर सकता है, तो वह निलंबित हो जाता है और वेटर सूची पर प्रतीक्षा करता है कि उसे बताया जाए (संकेतित) कि उसका संसाधन उपलब्ध है। वेटर सूची पर बिताया गया समय संसाधन प्रतीक्षा समय है और रननेबल कतार पर बिताया गया समय सिग्नल प्रतीक्षा समय है। साथ में वे समग्र प्रतीक्षा समय बनने के लिए गठबंधन करते हैं। SQL OS प्रतीक्षा समय और सिग्नल प्रतीक्षा समय का ट्रैक रखता है इसलिए हमें संसाधन प्रतीक्षा समय प्राप्त करने के लिए sys.dm_os_wait_stats से आउटपुट पर कुछ गणित करना होगा (मेरी स्क्रिप्ट यहां देखें)।
वेटर सूची अनियंत्रित है (इस पर किसी भी थ्रेड को किसी भी समय सिग्नल किया जा सकता है और रननेबल कतार में ले जाया जा सकता है) और रननेबल कतार लगभग 100% समय पहले-इन-फर्स्ट-आउट (फीफो) है। रननेबल कतार के फीफो होने का एकमात्र अपवाद यह है कि एक ही संसाधन पूल में कई संसाधन गवर्नर वर्कलोड समूह कॉन्फ़िगर किए गए हैं और उनकी एक दूसरे के सापेक्ष अलग-अलग प्राथमिकताएं हैं। मैंने इसे उत्पादन में सफलतापूर्वक उपयोग करते नहीं देखा है इसलिए मैं इसके बारे में आगे चर्चा नहीं करूंगा।
एक और कारण है कि एक थ्रेड को प्रोसेसर से दूर जाने की आवश्यकता हो सकती है - यह इसकी मात्रा को समाप्त कर देता है। SQL OS में थ्रेड क्वांटम 4 मिलीसेकंड पर तय होता है। थ्रेड स्वयं यह निर्धारित करने के लिए ज़िम्मेदार है कि इसकी मात्रा समाप्त हो गई है (एसक्यूएल ओएस में सहायक दिनचर्या को कॉल करके) और स्वेच्छा से प्रोसेसर को छोड़ रहा है (जिसे उपज कहा जाता है)। जब ऐसा होता है, तो थ्रेड सीधे रननेबल कतार के निचले भाग में चला जाता है, क्योंकि इसमें प्रतीक्षा करने के लिए कुछ भी नहीं होता है। SQL OS को प्रोसेसर से इस संक्रमण के लिए प्रतीक्षा प्रकार पंजीकृत करना होगा, और SOS_SCHEDULER_YIELD को पंजीकृत करना होगा।
यह व्यवहार अक्सर CPU दबाव के लिए गलत होता है, लेकिन ऐसा नहीं है - यह केवल निरंतर CPU उपयोग है। सीपीयू दबाव, और इसे पहचानना, भविष्य की पोस्ट के लिए एक अन्य विषय है। जहां तक इस पोस्ट का संबंध है, जब तक औसत सिग्नल प्रतीक्षा समय कम है (0-0.1-0.2ms), यह एक बहुत ही सुरक्षित शर्त है कि CPU दबाव कोई समस्या नहीं है।
स्पिनलॉक
एक स्पिनलॉक एक बहुत ही निम्न-स्तरीय सिंक्रनाइज़ेशन आदिम है जिसका उपयोग SQL सर्वर में डेटा संरचनाओं तक थ्रेड-सुरक्षित पहुंच प्रदान करने के लिए किया जाता है जो बेहद गर्म होते हैं (बहुत अस्थिर और एक्सेस किए जाते हैं और कई थ्रेड्स द्वारा अविश्वसनीय रूप से अक्सर बदलते हैं)। ऐसी संरचनाओं के उदाहरण बफ़र पूल के प्रत्येक भाग में बफ़र मुक्त सूची और फ़ाइल समूह में डेटा फ़ाइलों के लिए आनुपातिक-भरण भार सरणी हैं।
जब एक थ्रेड को स्पिनलॉक प्राप्त करने की आवश्यकता होती है, तो यह देखने के लिए लगता है कि क्या स्पिनलॉक मुक्त है और यदि ऐसा है तो तुरंत इसे प्राप्त कर लेता है (एक इंटरलॉक्ड असेंबली-भाषा आदिम जैसे 'टेस्ट बिट क्लियर एंड सेट' का उपयोग करके)। यदि स्पिनलॉक का अधिग्रहण नहीं किया जा सकता है, तो धागा तुरंत इसे फिर से हासिल करने की कोशिश करता है, और फिर से, और फिर से, एक हजार पुनरावृत्तियों तक, जब तक कि यह बैक ऑफ नहीं हो जाता (थोड़ा सो जाता है)। यह किसी भी प्रतीक्षा प्रकार के रूप में पंजीकृत नहीं होता है, क्योंकि थ्रेड केवल विंडोज स्लीप () फ़ंक्शन को कॉल करता है, लेकिन प्रतीक्षा कर रहे अन्य थ्रेड्स में बड़े (10-20ms+) सिग्नल प्रतीक्षा समय हो सकते हैं क्योंकि स्लीपिंग थ्रेड प्रोसेसर पर तब तक रहता है जब तक स्पिनलॉक प्राप्त करता है।
मैं स्पिनलॉक्स के बारे में क्यों बात कर रहा हूँ? क्योंकि वे उच्च CPU उपयोग का कारण भी हो सकते हैं, और एक गलत धारणा है कि स्पिनलॉक्स SOS_SCHEDULER_YIELD प्रतीक्षा का कारण हैं। वे नहीं हैं।
SOS_SCHEDULER_YIELD कारण
तो SOS_SCHEDULER_YIELD के लिए एक कारण है:एक थ्रेड अपने शेड्यूलिंग क्वांटम को समाप्त कर देता है और भारी आवर्ती उदाहरणों के कारण उच्च CPU उपयोग के साथ SOS_SCHEDULER_YIELD सबसे प्रचलित प्रतीक्षा हो सकती है।
आप SOS_SCHEDULER_YIELD प्रतीक्षा को sys.dm_os_waiting_tasks से आउटपुट में दिखाई नहीं देंगे, क्योंकि थ्रेड प्रतीक्षा नहीं कर रहा है। आप sys.dm_exec_requests को क्वेरी करके और last_wait_type कॉलम पर फ़िल्टर करके देख सकते हैं कि कौन सी क्वेरी SOS_SCHEDULER_YIELD वेट जनरेट कर रही है।
इसका यह भी अर्थ है कि जब आप sys.dm_os_wait_stats के आउटपुट में SOS_SCHEDULER_YIELD देखते हैं, तो संसाधन प्रतीक्षा शून्य होगी, क्योंकि यह वास्तव में प्रतीक्षा नहीं करता था। लेकिन याद रखें कि इनमें से प्रत्येक 'वेट्स' क्वेरी के लिए अर्जित 4ms CPU समय के बराबर होता है।
यह साबित करने का एकमात्र तरीका है कि SOS_SCHEDULER_YIELD प्रतीक्षा का कारण SQL सर्वर कॉल स्टैक को कैप्चर करना है, जब वह प्रतीक्षा प्रकार होता है, Microsoft से विस्तारित ईवेंट और डीबग प्रतीकों का उपयोग करके। मेरे पास एक ब्लॉग पोस्ट है जो बताती है और दिखाती है कि उस जांच को कैसे किया जाए, और स्पिनलॉक और स्पिनलॉक जांच के बारे में एक महान श्वेतपत्र है जो पढ़ने योग्य है यदि आप आंतरिक की गहराई में रुचि रखते हैं।
क्वांटम थकावट के मामले में, यह मूल कारण नहीं है। यह एक और लक्षण है। अब हमें इस बात पर विचार करने की आवश्यकता है कि एक धागा बार-बार अपनी मात्रा को क्यों समाप्त कर रहा है।
एक थ्रेड केवल अपने क्वांटम को समाप्त कर सकता है जब वह किसी अन्य थ्रेड के संसाधन की आवश्यकता के बिना 4ms के लिए SQL सर्वर कोड को संसाधित करना जारी रख सकता है - लॉक, पेज लैच, डिस्क से डेटा फ़ाइल पेज पढ़ने के लिए कोई प्रतीक्षा नहीं, मेमोरी आवंटन, फ़ाइल वृद्धि, लॉगिंग , या असंख्य अन्य संसाधन जिनकी एक थ्रेड को आवश्यकता हो सकती है।
कोड का सबसे आम टुकड़ा जहां क्वांटम थकावट हो सकती है और बड़ी मात्रा में SOS_SCHEDULER_YIELD प्रतीक्षा कर सकता है एक इंडेक्स/टेबल स्कैन कर रहा है जहां सभी आवश्यक डेटा फाइल पेज मेमोरी में हैं और उन पेजों तक पहुंच के लिए कोई विवाद नहीं है, और यही है जब आप SOS_SCHEDULER_YIELD को शीर्ष प्रतीक्षा प्रकार के रूप में देखते हैं - बड़े और/या दोहराए गए इंडेक्स/टेबल स्कैन के रूप में देखने के लिए मैं आपको क्वेरी योजनाओं में देखने के लिए प्रोत्साहित करता हूं।
इसका मतलब यह नहीं है कि मैं कह रहा हूं कि बड़े स्कैन खराब हैं, क्योंकि यह हो सकता है कि आपके कार्यभार को संसाधित करने का सबसे कुशल तरीका स्कैन के माध्यम से हो। हालांकि, यदि SOS_SCHEDULER_YIELD प्रतीक्षा नई और असामान्य है, और बड़े स्कैन के कारण होती है, तो आपको जांच करनी चाहिए कि क्वेरी योजना स्कैन का उपयोग क्यों कर रही है। हो सकता है कि किसी ने एक महत्वपूर्ण गैर-संकुल सूचकांक गिरा दिया हो, या आंकड़े पुराने हैं और इसलिए एक गलत क्वेरी योजना चुनी गई थी, या हो सकता है कि एक असामान्य पैरामीटर मान एक संग्रहीत प्रक्रिया और स्कैन के लिए बुलाए गए क्वेरी प्लान, या एक कोड परिवर्तन के लिए पारित किया गया हो। अनुक्रमणिका परिवर्धन का समर्थन किए बिना हुआ।
सारांश
अन्य प्रतीक्षा प्रकारों की तरह ही, SOS_SCHEDULER_YIELD का सही अर्थ यह समझना महत्वपूर्ण है कि इसका निवारण कैसे किया जाए, और कार्यभार संसाधित होने के कारण व्यवहार अपेक्षित है या नहीं।
जहां तक सामान्य प्रतीक्षा आंकड़ों का संबंध है, आप प्रदर्शन समस्या निवारण के लिए उनका उपयोग करने के बारे में अधिक जानकारी यहां प्राप्त कर सकते हैं:
- मेरी SQLskills ब्लॉग पोस्ट श्रृंखला, प्रतीक्षा आँकड़ों से शुरू होती है, या कृपया मुझे बताएं कि यह कहाँ दर्द होता है
- मेरे प्रतीक्षा प्रकार और कुंडी कक्षा पुस्तकालय यहां
- मेरा प्लूरलसाइट ऑनलाइन प्रशिक्षण पाठ्यक्रम SQL सर्वर:प्रतीक्षा सांख्यिकी का उपयोग करके प्रदर्शन समस्या निवारण
- एसक्यूएल संतरी प्रदर्शन सलाहकार
श्रृंखला के अगले लेख में, मैं एक और प्रतीक्षा प्रकार पर चर्चा करूँगा जो घुटने के बल चलने वाली प्रतिक्रियाओं का एक सामान्य कारण है। तब तक, समस्या निवारण के लिए शुभकामनाएँ!