5

मुझे प्रदर्शन में सुधार करने के लिए काम किया गया है (और यह मेरा पहला वास्तविक-दुनिया प्रदर्शन ट्यूनिंग है) एक एसएसआरएस फ्रंट-एंड द्वारा संग्रहीत रिपोर्टिंग प्रक्रिया के लिए और संग्रहीत प्रक्रिया में वर्तमान में लगभग 30 सेकंड लगते हैं डेटा की सबसे बड़ी मात्रा (रिपोर्ट फ्रंटेंड से सेट फ़िल्टर के आधार पर) पर चलाएं।संग्रहीत प्रक्रिया निष्पादन समय की रिपोर्टिंग में सुधार - अस्थायी तालिकाओं को ट्यून करना?

इस संग्रहीत प्रक्रिया में 1 9 प्रश्नों का निष्पादन टूट गया है, जिनमें से अधिकांश बेस टेबल के अंदर से प्रारंभिक (विरासत) प्रारूप से डेटा को व्यावसायिक साइड में प्रदर्शित होने के लिए एक सार्थक डेटासेट में बदल रहे हैं।

मैंने कुछ डीएमवी के आधार पर एक क्वेरी बनाई है ताकि यह पता चल सके कि संग्रहीत प्रक्रिया (नीचे छोटे स्निपेट) से सबसे अधिक संसाधन लेने वाले प्रश्न कौन से हैं और मुझे एक क्वेरी मिली है जिसमें लगभग 10 सेकंड लगते हैं औसत, पूरा करने के लिए।

select 
    object_name(st.objectid)                 [Procedure Name] 
    , dense_rank() over (partition by st.objectid order by qs.last_elapsed_time desc)   [rank-execution time] 
    , dense_rank() over (partition by st.objectid order by qs.last_logical_reads desc)   [rank-logical reads] 
    , dense_rank() over (partition by st.objectid order by qs.last_worker_time desc)   [rank-worker (CPU) time] 
    , dense_rank() over (partition by st.objectid order by qs.last_logical_writes desc)   [rank-logical write] 
     ... 
from sys.dm_exec_query_stats as qs 
    cross apply sys.dm_exec_sql_text (qs.sql_handle) as st 
    cross apply sys.dm_exec_text_query_plan (qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) as qp 
where st.objectid in (object_id('SuperDooperReportingProcedure')) 
    , [rank-execution time] 
    , [rank-logical reads] 
    , [rank-worker (CPU) time] 
    , [rank-logical write] desc 

अब, यह क्वेरी कार्य योजना लागू करके पता चलता है कि पता चलता है कि काम (~ 80%) के थोक किया जाता है जब जब नहीं स्थानीय अस्थायी तालिका में डेटा डालने और अर्थ में थोड़ा अजीब है उन अन्य तालिकाओं से पूछताछ करें जिनसे स्रोत डेटा लिया जाता है और फिर छेड़छाड़ की जाती है। अर्थ में (नीचे स्क्रीनशॉट एसक्यूएल संतरी योजना एक्सप्लोरर से है)

enter image description here

इसके अलावा, पंक्ति अनुमान के मामले में, कार्य योजना लागू करके इस के लिए जिस तरह से बंद अनुमान है, केवल 4218 स्थानीय में डाला पंक्तियों देखते हैं कि अस्थायी तालिका ~ 248k पंक्तियों के विपरीत है कि निष्पादन योजना स्थानीय अस्थायी तालिका में जाने के बारे में सोचती है। तो, इसके कारण, मैं "आंकड़े" सोच रहा हूं, लेकिन फिर भी उन लोगों को भी कोई फर्क नहीं पड़ता कि काम का 80% वास्तविक तालिका में डालने वाला है?

मेरी पहली सिफारिशों में से एक पूरी प्रक्रिया और संग्रहीत प्रक्रिया को दोबारा लिखना था ताकि डेटा की चलती प्रक्रिया को रिपोर्टिंग प्रक्रिया में बदलना और बदलना शामिल न हो और डेटा को कुछ स्थिर तालिकाओं में रात में बदलने के लिए (रीयल-टाइम डेटा की आवश्यकता नहीं है, केवल पिछले दिन के अंत तक प्रासंगिक डेटा)। लेकिन व्यावसायिक पक्ष समय और संसाधनों को फिर से डिजाइन करने के लिए निवेश नहीं करना चाहता है और इसके बजाय "सुझाव देता है" मैं यह जानने के अर्थ में प्रदर्शन ट्यूनिंग करता हूं कि मैं इसे और कहां जोड़ सकता हूं।

मुझे विश्वास नहीं है कि बेस टेबल पर इंडेक्स जोड़ने से रिपोर्ट के प्रदर्शन में सुधार होगा क्योंकि क्वेरी चलाने के लिए आवश्यक अधिकांश समय डेटा को एक अस्थायी तालिका में सहेज रहा है (जो मेरे ज्ञान से यह tempdb को हिट करेगा, जिसका अर्थ है कि उन्हें डिस्क पर लिखा जाएगा -> I/O विलंबता के कारण बढ़ी हुई समय)।

लेकिन, जैसा कि मैंने उल्लेख किया है, यह मेरा पहला प्रदर्शन ट्यूनिंग कार्य है और मैंने पिछले कुछ दिनों में जितना संभव हो सके इसे पढ़ने की कोशिश की है और ये मेरे निष्कर्ष अब तक हैं, लेकिन मैं व्यापक दर्शकों से सलाह मांगना चाहता हूं और आशा करता हूं कि इस प्रक्रिया को बेहतर बनाने के लिए मैं कुछ और अंतर्दृष्टि और समझ प्राप्त कर सकता हूं।

में कुछ स्पष्ट सवाल है, तो जवाब हो सकता है मैं इसकी सराहना करेंगे के रूप में कर रहे हैं:

  • क्या क्या मैं ऊपर कहा है में गलत (db या मेरे मान्यताओं की मेरी समझ में) है?
  • क्या यह सच है कि एक अस्थायी तालिका में एक इंडेक्स जोड़ने से वास्तव में निष्पादन का समय बढ़ जाएगा, क्योंकि तालिका (और इसके संबंधित इंडेक्स (एसएस) को प्रत्येक निष्पादन पर पुनर्निर्मित किया जा रहा है)?
  • क्या इस परिदृश्य में प्रक्रिया/प्रश्नों को दोबारा लिखने के बिना और कुछ भी किया जा सकता है और केवल इंडेक्स या अन्य ट्यूनिंग विधियों के माध्यम से किया जा सकता है? (मैंने कुछ लेख शीर्षकों को पढ़ा है कि आप "tempdb को भी ट्यून कर सकते हैं", लेकिन मुझे अभी तक उन विवरणों में शामिल नहीं किया गया है)।

किसी भी मदद की बहुत सराहना की जाती है और यदि आपको अधिक जानकारी चाहिए तो मुझे पोस्ट करने में खुशी होगी।

अद्यतन (2 अगस्त 2016):

प्रश्न में क्वेरी (आंशिक रूप से) नीचे है।

select 
    b.ProgramName 
    ,b.Region 
    ,case when b.AM IS null and b.ProgramName IS not null 
     then 'Unassigned' 
     else b.AM 
    end as AM 
    ,rtrim(ltrim(b.Store)) Store 
    ,trd.Store_ID 
    ,b.appliesToPeriod 
    ,isnull(trd.countLeadActual,0) as Actual 
    ,isnull(sum(case when b.budgetType = 0 and b.budgetMonth between @start_date and @end_date then b.budgetValue else 0 end),0) as Budget 
    ,isnull(sum(case when b.budgetType = 0 and b.budgetMonth between @start_date and @end_date and (trd.considerMe = -1 or b.StoreID < 0) then b.budgetValue else 0 end),0) as CleanBudget 
    ... 
into #SalvesVsBudgets 
from #StoresBudgets b 
    left join #temp_report_data trd on trd.store_ID = b.StoreID and trd.newSourceID = b.ProgramID 
where (b.StoreDivision is not null or (b.StoreDivision is null and b.ProgramName = 'NewProgram')) 
    group by 
     b.ProgramName 
     ,b.Region 
     ,case when b.AM IS null and b.ProgramName IS not null 
      then 'Unassigned' 
      else b.AM 
     end 
    ,rtrim(ltrim(b.Store)) 
    ,trd.Store_ID 
    ,b.appliesToPeriod 
    ,isnull(trd.countLeadActual,0) 

मुझे यकीन है कि अगर यह वास्तव में उपयोगी है नहीं कर रहा हूँ, लेकिन जब से @kcung यह अनुरोध किया है, मैं जानकारी कहा: क्या याद आ रही है कुछ और कुल कॉलम और GROUP BY अनुभाग में उनकी संगत लाइनें हैं।

इसके अलावा, कुछ उसके सवालों का जवाब करने के लिए:

  • अस्थायी तालिकाओं उन पर कोई अनुक्रमणिका है
  • रैम का आकार: 32 जीबी

अद्यतन (3 अगस्त 2016):

मैंने कुल-उत्पन्न क्वेरी और दुर्भाग्य से CASE कथन को स्थानांतरित करने के लिए @ kcung के सुझावों का प्रयास किया है कुल मिलाकर, कुल मिलाकर, प्रक्रिया समय में सुधार नहीं हुआ है, ध्यान में, क्योंकि यह अभी भी ± 0.25 से ± 1.0 सेकंड की सीमा में उतार-चढ़ाव करता है (हां, संग्रहित प्रक्रिया के मूल संस्करण की तुलना में निचला और उच्च समय दोनों - लेकिन मैं इसका अनुमान लगा रहा हूं मेरी मशीन पर परिवर्तनीय वर्कलोड के कारण है)।

समान क्वेरी के लिये कार्य योजना है, लेकिन केवल SUM समुच्चय छोड़ने CASE की स्थिति को दूर करने के लिए संशोधित, अब है:

enter image description here

उत्तर

0

किसी भी मौका मैं क्वेरी देख सकते हैं? और दोनों टेबल पर इंडेक्स? आपका राम कितना बड़ा है? प्रत्येक तालिका में पंक्ति कितनी बड़ी है (मोटे तौर पर)? क्या आप दोनों तालिकाओं के आंकड़े अपडेट कर सकते हैं और क्वेरी प्लानर भेज सकते हैं?

  1. आप ज्यादातर सही, अनुक्रमित जोड़ने के हिस्से को छोड़कर कर रहे हैं:

    आपके प्रश्न का उत्तर करने के लिए। इंडेक्स जोड़ने से क्वेरी को लुकअप करने में मदद मिलेगी। यह हैश प्लान की बजाय नेस्टेड लूप जॉइन प्लान पर विचार करने के लिए क्वेरी प्लानर को मौका भी देगा। दुर्भाग्यवश, जब तक मेरे प्रश्न का उत्तर नहीं दिया जाता तब तक मैं और अधिक जवाब नहीं दे सकता।

  2. आपको temp तालिका में अनुक्रमणिका जोड़ने की आवश्यकता नहीं है। इस अस्थायी (या किसी भी सम्मिलित गंतव्य तालिका) तालिका में इंडेक्स जोड़ना लिखने का समय बढ़ाएगा, क्योंकि डालने के लिए उस इंडेक्स को अपडेट करना होगा। बस कम से कम जानकारी के साथ अपनी तालिका की प्रति के रूप में एक इंडेक्स की कल्पना करें और यह आपकी तालिका के शीर्ष पर बैठता है और इसे आपकी तालिका के साथ समन्वयित करने की आवश्यकता है। इस इंडेक्स को अपडेट करने के लिए प्रत्येक लिखना (डालें, अपडेट करें, हटाएं) की आवश्यकता है।
  3. दोनों पंक्तियों को कुल पंक्तियों को देखते हुए, यह क्वेरी 10s से अधिक तेज़ी से चलनी चाहिए, जब तक कि आपके पास नींबू पीसी न हो, तो यह एक अलग कहानी है।

संपादित करें: बस बिंदु 2 के लिए बाहर बात करने के लिए चाहते हैं, मैं तुम्हें रहे स्रोत तालिका अस्थायी तालिका के रूप में अच्छी तरह से है एहसास नहीं था। एक कनेक्शन समाप्त होने के प्रत्येक सत्र के बाद अस्थायी तालिका नष्ट हो जाती है। अस्थायी तालिका में इंडेक्स जोड़ना मतलब है कि जब भी आप इस अस्थायी तालिका को बनाते हैं तो आप इस इंडेक्स को बनाने के लिए अतिरिक्त समय जोड़ देंगे।

संपादित करें: क्षमा करें, मैं अब फोन का उपयोग कर रहा हूं। मैं बस छोटा होने वाला हूँ। तो अनिवार्य रूप से 2 बातें:

  • अस्थायी तालिका निर्माण समय पर प्राथमिक कुंजी जोड़ें ताकि आप एक ही बार में करते हैं। नॉनक्लस्टर्ड इंडेक्स या किसी भी कवरिंग इंडेक्स को जोड़ने से परेशान न हों, जिससे आप उन्हें बनाने में अधिक समय व्यतीत करेंगे।

  • अपनी क्वेरी देखें, सभी प्रश्नों के दौरान, इस प्रश्न में ऐसा करने के बजाय, आप उन्हें तालिका में किसी अन्य कॉलम के रूप में क्यों नहीं जोड़ते हैं। अनिवार्य रूप से आप समूह द्वारा करते समय फ्लाई पर गणना से बचना चाहते हैं। आप क्वेरी में sum() को छोड़ सकते हैं क्योंकि यह एक समग्र क्वेरी है, लेकिन जितना संभव हो सके रन टाइम गणना को कम करें और कम करें।

नमूना:

case when b.AM IS null and b.ProgramName IS not null 
    then 'Unassigned' 
    else b.AM 
end as AM 

आप तालिका ख बनाते समय पूर्वाह्न नाम के एक स्तंभ बना सकते हैं। भी उन आरआरटीआईएम और एलटीआईएमआईएम। कृपया उन्हें हटाएं और इसे टेबल निर्माण समय में चिपकाएं। :)

+0

1. अधिक जानकारी के साथ प्रश्नों को अपडेट किया गया। –

+0

2. अस्थायी तालिकाओं पर कोई अनुक्रमणिका नहीं। –

+0

4. क्या आप यहां पृष्ठ विखंडन के बारे में सोच रहे हैं? –

0
  1. अस्थायी तालिका में अनुक्रमणिका जोड़ना निश्चित रूप से पढ़ने की कॉल में सुधार करेगा लेकिन अस्थायी तालिका में लिखने के कॉल को धीमा कर देगा।
  2. जैसा कि आपने बताया है, प्रक्रिया में निष्पादित 1 9 प्रश्न हैं, इसलिए निष्पादन योजना के साथ केवल एक प्रश्न का विश्लेषण करना अधिक उपयोगी नहीं होगा।
  3. यदि संभव हो तो अधिक जोड़ना, इस क्वेरी को केवल & निष्पादित करें यह जांचें कि कितना समय लगता है (पंक्तियां प्रभावित)।
  4. अन्य दृष्टिकोण आप कोशिश कर सकते हैं, सुनिश्चित करें कि आपके मामले में संभव है, तो अस्थायी तालिका के बजाय तालिका चर का उपयोग करने का प्रयास करें। ऐसा इसलिए है क्योंकि, अस्थायी तालिका में तालिका चर का उपयोग करने के अतिरिक्त फायदे हैं जैसे प्रक्रिया पूर्व-संकलित है, कोई लेनदेन लॉग बनाए रखा नहीं जाता है। & और, आपको ड्रॉप टेबल लिखने की आवश्यकता नहीं है।
+0

2. अधिकांश प्रश्न एक टेम्पलेट टेबल से दूसरे में 'SELECT'' हैं ('से चुनें'), कुछ और जोड़ों के आधार पर डेटा के कुछ संशोधनों के साथ/समेकित इत्यादि। और कुछ और प्रश्न हैं जो लगभग 15 और सेकंड तक हैं (लेकिन वे 4-5 प्रश्न हैं, न कि 1)। इसलिए, मैं इस बड़ी क्वेरी से जितना संभव हो उतना समय निकालना चाहता हूं दूसरों को जाने से पहले, जो मुझे नहीं लगता कि उन्हें सुधार किया जा सकता है (अभी तक)। –

+0

3. मुझे नहीं लगता कि मैं अधिक विस्तृत जानकारी प्राप्त कर सकता हूं डीएमवी के अलावा अन्य प्रश्नों से इन प्रश्नों को झुकाएं। इसलिए, एक समय में अधिक प्रश्नों को जोड़ने/परीक्षण करने से मुझे कुछ नया खोजने में मदद नहीं मिलेगी क्योंकि मुझे पहले से ही पता है कि यह कितना समय लगता है और मेरे "अपराधी" कौन हैं। –

+0

4. मैंने तालिका चर का प्रयास किया है और निष्पादन समय में सुधार हुआ है, लेकिन लगभग 25 बार दोहराए गए निष्पादन के बाद केवल 5-10% (0.25 - 1 सेकंड) तक, औसत पर यह लगभग 0.5 सेकंड है। और मैं "सर्वर" लोड पर इस श्रेणी को "दोष" दे सकता हूं। साथ ही, जो मुझे पता है, तालिका चर वे अभी भी tempdb हिट करेंगे अगर वे स्मृति में फिट नहीं होते हैं, इसलिए I/O विलंबता फिर से जोड़ दी गई है। मैं लेनदेन लॉग के बारे में सहमत हूं, लेकिन अब यह मेरी चिंता नहीं है और कुछ ऐसा नहीं जो व्यवसाय सुनना चाहता है (यदि यह ** समस्या को हल नहीं कर सकता **)। साथ ही, ड्रॉप टेबल स्पष्ट रूप से नहीं कहा गया है, अस्थायी तालिकाओं को सत्र के करीब नष्ट कर दिया जाता है। –

संबंधित मुद्दे