मैं एक आवेदन में धीमी गति से निदान करने की कोशिश कर रहा हूँ। इसके लिए मैंने SQL सर्वर विस्तारित घटनाओं को लॉग इन किया है ।
- इस सवाल के लिए मैं एक विशेष संग्रहित प्रक्रिया को देख रहा हूं।
- लेकिन एक दर्जन संग्रहीत प्रक्रियाओं का एक कोर सेट है जो समान रूप से सेब-से-सेब जांच के रूप में उपयोग किया जा सकता है
- और जब भी मैं मैन्युअल रूप से संग्रहीत प्रक्रियाओं में से एक को चलाता हूं, तो यह हमेशा तेज चलती है
- और यदि कोई उपयोगकर्ता फिर से प्रयास करता है: तो यह तेजी से चलेगा।
संग्रहीत प्रक्रिया का निष्पादन समय बेतहाशा भिन्न होता है। इस संग्रहीत कार्यविधि के बहुत सारे निष्पादन <1s में वापस आते हैं:
और उस "तेज" बाल्टी के लिए, यह 1s से बहुत कम है। यह वास्तव में लगभग 90 एमएस है:
लेकिन उपयोगकर्ताओं की एक लंबी पूंछ है, जिन्हें 2s, 3s, 4s सेकंड इंतजार करना पड़ता है। कुछ को १२, १३, १४ का इंतजार करना पड़ता है। फिर वास्तव में गरीब आत्माएं हैं जिन्हें 22, 23, 24 के दशक तक इंतजार करना पड़ता है।
और 30 के बाद, क्लाइंट एप्लिकेशन को छोड़ देता है, क्वेरी को रद्द कर देता है, और उपयोगकर्ता को 30 सेकंड इंतजार करना पड़ता था ।
करणीय खोजने के लिए सहसंबंध
इसलिए मैंने सहसंबंध बनाने की कोशिश की:
- अवधि बनाम तार्किक रीड
- अवधि बनाम शारीरिक रीड
- अवधि बनाम सीपीयू समय
और कोई भी कोई संबंध नहीं देता है; कोई भी कारण नहीं लगता है
अवधि बनाम तार्किक पढ़ता है : चाहे थोड़ा, या बहुत तार्किक पढ़ता हो, अवधि में अभी भी बेतहाशा वृद्धि होती है :
अवधि बनाम शारीरिक रीड : भले ही कैश से क्वेरी की सेवा नहीं की गई थी, और बहुत अधिक शारीरिक रीड की आवश्यकता थी, यह अवधि को प्रभावित नहीं करता है:
अवधि बनाम सीपीयू समय : क्या क्वेरी सीपीयू समय के 0s, या सीपीयू समय का एक पूर्ण 2.5s लिया, अवधि समान परिवर्तनशीलता है:
बोनस : मैंने देखा है कि Duration v Physical Reads और Duration v CPU time बहुत समान दिखते हैं। यह साबित होता है अगर मैं भौतिक समय के साथ सीपीयू समय को सहसंबंधित करने की कोशिश करता हूं:
बहुत सारे CPU उपयोग I / O से आते हैं। किसे पता था!
इसलिए यदि निष्पादन समय में अंतरों के लिए क्वेरी को निष्पादित करने के अधिनियम के बारे में कुछ भी नहीं है , तो क्या इसका मतलब यह है कि यह सीपीयू या हार्ड ड्राइव से असंबंधित कुछ है?
यदि सीपीयू या हार्ड ड्राइव अड़चन थी; यह अड़चन नहीं होगी?
अगर हम परिकल्पना करते हैं कि यह सीपीयू था जो अड़चन था; इस सर्वर के लिए सीपीयू अंडर-पावर्ड है:
- तब अधिक CPU समय का उपयोग करते हुए निष्पादन में अधिक समय नहीं लगेगा?
- चूंकि उन्हें ओवरलोड सीपीयू का उपयोग करके दूसरों के साथ पूरा करना है?
इसी तरह हार्ड-ड्राइव के लिए। अगर हम अनुमान लगाते हैं कि हार्ड-ड्राइव एक अड़चन थी; हार्ड-ड्राइव में इस सर्वर के लिए पर्याप्त रैंडम-पुट नहीं है:
- फिर अधिक भौतिक रीड्स का उपयोग करने में अधिक समय नहीं लगेगा?
- चूंकि उन्हें दूसरों के साथ ओवरलोड हार्ड ड्राइव I / O का उपयोग करके पूरा करना है?
संग्रहीत प्रक्रिया न तो प्रदर्शन करती है, न ही आवश्यकता होती है, कोई भी लिखता है।
- आमतौर पर यह 0 पंक्तियों (90%) को वापस करता है।
- कभी-कभी यह 1 पंक्ति (7%) लौटाएगा।
- शायद ही कभी यह 2 पंक्तियों (1.4%) को वापस करेगा।
- और सबसे बुरे मामलों में यह 2 से अधिक पंक्तियों (एक बार 12 पंक्तियों की वापसी) लौटा है
इसलिए ऐसा नहीं है कि यह डेटा की एक पागल मात्रा वापस कर रहा है।
सर्वर CPU उपयोग
सर्वर का प्रोसेसर उपयोग औसत लगभग 1.8% है, कभी-कभी स्पाइक के साथ 18% तक - इसलिए ऐसा नहीं लगता है कि सीपीयू लोड एक मुद्दा है:
इसलिए सर्वर CPU अतिभारित नहीं लगता है।
लेकिन सर्वर है आभासी ...
ब्रह्मांड के बाहर कुछ?
केवल एक चीज जो मैं सोच सकता हूं वह कुछ है जो सर्वर के ब्रह्मांड के बाहर मौजूद है।
- अगर यह तार्किक नहीं है
- और यह शारीरिक रीड नहीं है
- और यह सीपीयू उपयोग नहीं है
- और यह सीपीयू लोड नहीं है
और ऐसा नहीं है कि यह संग्रहीत कार्यविधि के पैरामीटर है (क्योंकि उसी क्वेरी को मैन्युअल रूप से जारी करना और इसमें 27 सेकंड नहीं लगते हैं - यह ~ 0 सेकंड लेता है)।
एक ही संकलित संग्रहीत कार्यविधि को चलाने के लिए सर्वर को कभी-कभी 30 सेकंड लेने के बजाय 0 सेकंड के लिए क्या हो सकता है।
- चौकियों?
यह एक वर्चुअल सर्वर है
- होस्ट ओवरलोडेड है?
- उसी मेजबान पर एक और वीएम?
सर्वर के विस्तारित घटनाओं के माध्यम से जाना; विशेष रूप से तब और कुछ नहीं होता है जब किसी क्वेरी को अचानक 20 सेकंड लगते हैं। यह ठीक चलता है, फिर ठीक नहीं चलने का फैसला करता है:
- 2 सेकेंड
- 1 सेकेंड
- 30 सेकंड
- तीन सेकंड
- 2 सेकेंड
और वहाँ कोई अन्य particuarly ज़ोरदार आइटम मुझे मिल सकता है। यह हर 2 घंटे के लेनदेन लॉग बैकअप के दौरान नहीं है।
और क्या हो सकता है?
क्या मैं इसके अलावा कुछ भी कह सकता हूं: "सर्वर" ?
संपादित करें : दिन के समय तक सहसंबंध
मुझे एहसास हुआ कि मैंने सब कुछ करने के लिए अवधि को सहसंबद्ध किया है:
- तार्किक पढ़ता है
- भौतिक पढ़ता है
- सि पि यु का उपयोग
लेकिन एक बात जो मैंने इसे नहीं बताया वह थी दिन का समय । शायद हर-2 घंटे की लेन-देन लॉग बैकअप है एक समस्या।
या शायद मंदी करते चौकियों दौरान chucks में होते हैं?
नहीं:
इंटेल Xeon गोल्ड क्वाड-कोर 6142।
संपादित करें - लोग क्वेरी निष्पादन योजना की परिकल्पना कर रहे हैं
लोग क्वेरी निष्पादन योजना की परिकल्पना कर रहे हैं "तेज" और "धीमी" के बीच अलग होना चाहिए। वो नहीं हैं।
और हम इसे निरीक्षण से तुरंत देख सकते हैं।
हम जानते हैं कि लंबी अवधि "खराब" निष्पादन योजना के कारण नहीं है:
- एक जिसने अधिक तार्किक रीड लिया
- एक जो अधिक CPU से जुड़ता है और अधिक जुड़ाव और महत्वपूर्ण लुकअप करता है
क्योंकि यदि रीड में वृद्धि, या सीपीयू में वृद्धि, क्वेरी अवधि में वृद्धि का कारण थी, तो हम पहले से ही ऊपर देख चुके होंगे। कोई संबंध नहीं है।
लेकिन सीपीयू-रीड्स एरिया उत्पाद मैट्रिक के खिलाफ अवधि को सहसंबंधित करने की कोशिश करता है:
वहाँ भी एक सहसंबंध कम हो जाता है - जो एक विरोधाभास है।
संपादित करें : बड़ी संख्या में मानों के साथ एक्सेल स्कैटर प्लॉट्स में बग को वर्कअराउंड करने के लिए तितर बितर आरेखों को अपडेट करें ।
अगला कदम
मेरा अगला कदम अवरुद्ध प्रश्नों के लिए सर्वर उत्पन्न करने के लिए किसी को प्राप्त करना होगा - 5 सेकंड के बाद:
EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE
यह स्पष्ट नहीं होगा कि प्रश्न 4 सेकंड के लिए अवरोधित हैं या नहीं । लेकिन शायद 5 सेकंड के लिए क्वेरी को ब्लॉक करने वाली कोई भी चीज़ 4 सेकंड के लिए भी ब्लॉक हो जाती है।
धीरे चलने वाले
यहाँ दो संग्रहीत कार्यविधियों को निष्पादित किया जा रहा है:
- `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
- `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
समान मापदंडों के साथ एक ही संग्रहित प्रक्रिया, बैक टू बैक चलती है:
| Duration (us) | CPU time (us) | Logical reads | Physical reads |
|---------------|---------------|---------------|----------------|
| 13,984,446 | 47,000 | 5,110 | 771 |
| 4,603,566 | 47,000 | 5,126 | 740 |
कॉल 1:
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
बुलाओ २
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
यह योजनाओं के समान होने के लिए समझ में आता है; यह एक ही संग्रहीत कार्यविधि को निष्पादित कर रहा है, एक ही पैरामीटर के साथ।








