विकल्प (रेडिपाइल) हमेशा तेज़ होता है; क्यों?


169

मुझे एक विषम स्थिति का सामना करना पड़ा जहां OPTION (RECOMPILE)मेरी क्वेरी के लिए अपील करने के कारण यह आधे से एक सेकंड में चलती है, जबकि इसे छोड़ने से क्वेरी पांच मिनट तक अच्छी तरह से चलती है।

यह वह स्थिति है जब क्वेरी क्वेरी एनालाइज़र से या मेरे C # प्रोग्राम के माध्यम से निष्पादित की जाती है SqlCommand.ExecuteReader()। कॉल करना (या कॉल नहीं करना) DBCC FREEPROCCACHEया DBCC dropcleanbuffersकोई फर्क नहीं पड़ता; क्वेरी परिणाम हमेशा तुरंत OPTION (RECOMPILE)और इसके बिना पाँच मिनट से अधिक समय तक वापस आ जाते हैं । क्वेरी को हमेशा समान मापदंडों के साथ कहा जाता है [इस परीक्षण के लिए]।

मैं SQL Server 2008 का उपयोग कर रहा हूं।

मैं एसक्यूएल लिखने के साथ काफी सहज हूं, लेकिन पहले कभी भी OPTIONक्वेरी में एक कमांड का उपयोग नहीं किया है और इस मंच पर पदों को स्कैन करने तक योजना कैश की पूरी अवधारणा से अपरिचित था। पदों से मेरी समझ यह है कि OPTION (RECOMPILE)एक महंगा ऑपरेशन है। यह स्पष्ट रूप से क्वेरी के लिए एक नई लुकअप रणनीति बनाता है। तो ऐसा क्यों है, कि बाद में आने वाले प्रश्न OPTION (RECOMPILE)इतने धीमे हैं? क्या पिछले प्रश्नों में लुकअप रणनीति का उपयोग नहीं किया जाना चाहिए जो पिछले कॉल पर गणना की गई थी जिसमें पुनर्मूल्यांकन संकेत शामिल था?

क्या यह अत्यधिक असामान्य है कि हर एक कॉल पर एक पुनर्मूल्यांकन संकेत की आवश्यकता है?

प्रवेश-स्तर के प्रश्न के लिए क्षमा करें, लेकिन मैं वास्तव में इसके प्रमुख या पूंछ नहीं बना सकता।

अद्यतन: मुझे क्वेरी पोस्ट करने के लिए कहा गया है ...

select acctNo,min(date) earliestDate 
from( 
    select acctNo,tradeDate as date 
    from datafeed_trans 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_money 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_jnl 
    where feedid=@feedID and feedDate=@feedDate 
)t1 
group by t1.acctNo
OPTION(RECOMPILE)

क्वेरी विश्लेषक से परीक्षण चलाते समय, मैं निम्नलिखित पंक्तियों को प्रस्तुत करता हूं:

declare @feedID int
select @feedID=20

declare @feedDate datetime
select @feedDate='1/2/2009'

जब इसे मेरे C # प्रोग्राम से कॉल किया जाता है, तो पैरामीटर को SqlCommand.Parametersसंपत्ति के माध्यम से पारित किया जाता है ।

इस चर्चा के प्रयोजनों के लिए, आप मान सकते हैं कि पैरामीटर कभी नहीं बदलते हैं, इसलिए हम उप-इष्टतम पैरामीटर को कारण के रूप में सूंघ कर बता सकते हैं।


3
क्वेरी के पैरामीटर क्या हैं? इस लेख को देखें। blogs.msdn.com/b/turgays/archive/2013/09/10/… असल में, एसक्यूएल मापदंडों के आधार पर क्वेरी योजना उत्पन्न करने का प्रयास करता है जब खरीद पहले संकलित की जाती है। यह एक योजना उत्पन्न कर सकता है जो अलग नहीं है जब आप अलग-अलग, संभवतः अधिक यथार्थवादी मापदंडों को पारित करना शुरू करते हैं
स्पार्की

3
क्या क्वेरी को यहाँ सूचीबद्ध करने के लिए पर्याप्त है? मुझे लगता है कि स्पार्की सही है और यह संभवतः पैरामीटर सूँघने से संबंधित है, मुझे एक ऐसी ही समस्या थी जिसने इस उत्कृष्ट लेख को पढ़ने तक मुझे बाहर निकालने में भ्रमित किया: sommarskog.se/query-plan-mysteries.html
क्रिस

1
लेकिन इस मामले में (इस परीक्षण के लिए) मैं हमेशा एक ही पैरामीटर में गुजर रहा हूं। कोई अन्य ऐप अन्य पैरामैम्स का उपयोग करके क्वेरी को चुपके और कॉल करने में सक्षम नहीं थे। लेख के लिए धन्यवाद। समीक्षा करेंगे।
चाड डेकर

2
यह या तो हो सकता है क्योंकि यह मापदंडों और चर के मूल्यों को सूँघता है या क्योंकि यह अधिक सरलीकरण करता है। अधिक से अधिक सरलीकरण के उदाहरण एक साधक X = @X OR @X IS NULLको ढहाने X=@Xऔर प्रदर्शन करने के लिए मिलते हैं यहां देखें या खिड़की के कार्यों के साथ एक दृश्य के खिलाफ आगे की भविष्यवाणी करें
मार्टिन स्मिथ

3
क्वेरी एनालाइज़र उदाहरण को संपादित करने के बाद, चर नहीं मापदंडों का उपयोग करता है। उन का मूल्य कभी नहीं सूँघा है सिवाय इसके RECOMPILE। किसी भी घटना में निष्पादन योजनाओं को पकड़ें और मतभेदों को देखें।
मार्टिन स्मिथ

जवाबों:


157

ऐसे समय होते हैं जब उपयोग करने OPTION(RECOMPILE)से समझ में आता है। मेरे अनुभव में केवल यही एक व्यवहार्य विकल्प है जब आप गतिशील एसक्यूएल का उपयोग कर रहे हैं। इससे पहले कि आप यह समझें कि इससे आपकी स्थिति में कोई फर्क पड़ता है या नहीं, मैं आपके आँकड़ों के पुनर्निर्माण की सिफारिश करूँगा। यह निम्नलिखित चलाकर किया जा सकता है:

EXEC sp_updatestats

और फिर अपनी निष्पादन योजना को फिर से बनाना। यह सुनिश्चित करेगा कि जब आपकी निष्पादन योजना बनाई जाएगी तो वह नवीनतम जानकारी का उपयोग कर रही होगी।

जोड़ा जा रहा है OPTION(RECOMPILE)rebuilds निष्पादन हर बार आपकी क्वेरी निष्पादित की योजना है। मैंने ऐसा कभी नहीं सुना है जो वर्णित है creates a new lookup strategyलेकिन शायद हम एक ही चीज़ के लिए अलग-अलग शब्दों का उपयोग कर रहे हैं।

जब एक संग्रहीत कार्यविधि बनाई जाती है (मुझे संदेह है कि आप .NET से ad-hoc sql को कॉल कर रहे हैं, लेकिन यदि आप एक पैरामीटर क्वेरी का उपयोग कर रहे हैं, तो यह एक संग्रहित कॉल कॉल समाप्त होता है ) SQL सर्वर इस क्वेरी के लिए सबसे प्रभावी निष्पादन योजना निर्धारित करने का प्रयास करता है। आपके डेटाबेस में डेटा और ( पैरामीटर सूँघने ) में पारित पैरामीटर के आधार पर , और फिर इस योजना को कैश करता है। इसका मतलब है कि यदि आप क्वेरी बनाते हैं जहां आपके डेटाबेस में 10 रिकॉर्ड हैं और फिर इसे निष्पादित करें जब 100,000,000 रिकॉर्ड किए गए कैश्ड निष्पादन योजना अब सबसे प्रभावी नहीं हो सकती है।

सारांश में - मुझे ऐसा कोई कारण नहीं दिख रहा है जो OPTION(RECOMPILE)यहां लाभकारी हो। मुझे संदेह है कि आपको अपने आंकड़े और अपनी निष्पादन योजना को अपडेट करने की आवश्यकता है। आपकी स्थिति के आधार पर पुनर्निर्माण के आंकड़े डीबीए के काम का एक अनिवार्य हिस्सा हो सकते हैं। यदि आपको अपने आँकड़े अपडेट करने के बाद भी समस्या हो रही है, तो मैं दोनों निष्पादन योजनाओं को पोस्ट करने का सुझाव दूंगा।

और आपके प्रश्न का उत्तर देने के लिए - हाँ, मैं कहूंगा कि आपके द्वारा क्वेरी को निष्पादित करने पर हर बार निष्पादन योजना को फिर से लागू करने के लिए यह सबसे अच्छा विकल्प है।


22
हां, sp_updatestats ने चाल चली। जब आप शुरू में 10 अभिलेखों के साथ तालिका पर चलते हैं, और अब तालिका में लाखों रिकॉर्ड होते हैं, तो आपने उस कील को सिर पर मारा। मेरा मामला ठीक यही था। मैंने पोस्ट में इसका उल्लेख नहीं किया क्योंकि मुझे नहीं लगा कि यह मामला था। आकर्षक सामान। एक बार फिर धन्यवाद।
चाड डेकर

3
यह एकमात्र तरीका है जिसे मैंने टेबल-वेरिएबल्स के साथ काम करने के लिए पाया है, क्योंकि एसक्यूएल हमेशा सोचता है कि इसमें एक एकल पंक्ति है। जब इसमें कई हजारों पंक्तियाँ होती हैं तो यह एक समस्या बन जाती है।
एलेक्स

4
एक दिलचस्प विवरण: आँकड़े अद्यतन करना सभी कैश्ड योजनाओं को अवैध रूप से अमान्य कर देता है जो इन आँकड़ों का उपयोग करते हैं, लेकिन केवल अगर आँकड़े वास्तव में अद्यतन कार्रवाई के बाद बदल गए । इसलिए अत्यधिक टेढ़ी मेढ़ी टेबलों के लिए, ऐसा लगता है कि एक स्पष्ट OPTION (RECOMPILE)एकमात्र समाधान हो सकता है।
ग्रू

141

अक्सर जब किसी प्रश्न को चलाने के लिए रन से काफी अंतर होता है, तो मुझे लगता है कि यह अक्सर 5 मुद्दों में से एक है।

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

  2. PARAMETER SNIFFING - जिस क्वेरी प्लान को कैश किया गया है, वह उस विशेष पैरामीटर के लिए इष्टतम नहीं है, जिसमें आप पास हो रहे हैं, भले ही वह क्वेरी खुद नहीं बदली हो। उदाहरण के लिए, यदि आप किसी ऐसे पैरामीटर में पास होते हैं, जो केवल 1,000,000 पंक्तियों में से 10 को पुनर्प्राप्त करता है, तो बनाई गई क्वेरी योजना एक हैश जॉइन का उपयोग कर सकती है, हालांकि यदि आप जिस पैरामीटर से गुजरते हैं, वह 1,000,000 पंक्तियों में से 750,000 का उपयोग करेगा, तो बनाई गई योजना एक हो सकती है सूचकांक स्कैन या टेबल स्कैन। ऐसी स्थिति में आप SQL स्टेटमेंट को विकल्प (RECOMPILE) या SP का उपयोग करने के लिए विकल्प के साथ बता सकते हैं । इंजन को यह बताने के लिए कि यह "सिंगल यूज़ प्लान" है और कैश्ड प्लान का उपयोग नहीं करना है, जो संभवत: लागू नहीं होता है। यह निर्णय लेने का कोई नियम नहीं है, यह उपयोगकर्ताओं द्वारा क्वेरी का उपयोग करने के तरीके को जानने पर निर्भर करता है।

  3. संकेत - यह संभव है कि क्वेरी नहीं बदली गई है, लेकिन एक अन्य जगह जैसे कि एक बहुत ही उपयोगी सूचकांक को हटाने से एक बदलाव धीमा हो गया है।

  4. ROWS CHANGED - आपके द्वारा कॉल से कॉल में बड़े पैमाने पर बदलाव किए जा रहे हैं। आमतौर पर इन मामलों में आंकड़े स्वतः ही अपडेट हो जाते हैं। हालाँकि यदि आप डायनेमिक SQL बना रहे हैं या एक तंग लूप के भीतर SQL कॉल कर रहे हैं, तो ऐसी संभावना है कि आप एक पुरानी क्वेरी प्लान का उपयोग गलत पंक्तियों या आंकड़ों की गलत संख्या के आधार पर कर रहे हैं। इस मामले में फिर से विकल्प (RECOMPILE) उपयोगी है।

  5. लॉजिक इसका लॉजिक, आपकी क्वेरी अब कुशल नहीं है, यह छोटी संख्या में पंक्तियों के लिए ठीक था, लेकिन अब नहीं है। इसमें आमतौर पर क्वेरी प्लान का अधिक अनिश्चित विश्लेषण शामिल है। उदाहरण के लिए, आप अब बल्क में काम नहीं कर सकते हैं, लेकिन चीजों को चंक कर सकते हैं और छोटे कमिट्स कर सकते हैं, या आपका क्रॉस प्रोडक्ट छोटे सेट के लिए ठीक था, लेकिन अब सीपीयू और मेमोरी को ऊपर ले जाता है क्योंकि यह बड़ा होता है, यह सच भी हो सकता है DISTINCT का उपयोग करते हुए, आप प्रत्येक पंक्ति के लिए एक फ़ंक्शन कह रहे हैं, आपके प्रमुख मिलान किसी प्रकार के रूपांतरण या NULLS या फ़ंक्शंस के कारण एक इंडेक्स का उपयोग नहीं करते हैं ... यहां बहुत अधिक संभावनाएं हैं।

सामान्य तौर पर जब आप एक प्रश्न लिखते हैं, तो आपके पास कुछ मानसिक चित्र होना चाहिए कि आपकी तालिका के भीतर कुछ डेटा कैसे वितरित किया जाता है। उदाहरण के लिए एक कॉलम में विभिन्न मूल्यों की समान रूप से वितरित संख्या हो सकती है, या इसे तिरछा किया जा सकता है, 80% समय में मूल्यों का एक विशिष्ट सेट होता है, चाहे वितरण समय के साथ अलग-अलग हो या काफी स्थिर हो। यह आपको एक कुशल क्वेरी बनाने का एक बेहतर विचार देगा। लेकिन यह भी जब क्वेरी प्रदर्शन डिबगिंग के पास एक परिकल्पना बनाने का आधार होता है कि यह धीमा या अक्षम क्यों है।


2
धन्यवाद दोस्त। यह उत्कृष्ट जानकारी है। जब मैं मूल रूप से अपना प्रश्न पोस्ट करता हूं, तो मैं आपके उत्तर को समझने में सक्षम नहीं होता, लेकिन अब यह मेरे लिए सही अर्थ रखता है।
चाड डेकर

3
PARAMETER SNIFFING मेरे अस्तित्व का अब तक का सबसे बड़ा बैन है। मुझे इस आदेश के बारे में तब तक पता नहीं चला जब तक कि एक असफल साक्षात्कार प्रश्न नहीं था। पैरामीटर सूँघने के लिए मेरा समाधान हमेशा पैरामीटर मानों को हैश करने के लिए रहा है और "और {हैश} = {हैश}" को जोड़ें ताकि एसक्यूएल हमेशा विभिन्न मूल्यों के लिए अलग हो। एक हैक, लेकिन यह काम किया।
जेरेमी बॉयड

27

उन स्थितियों की उत्कृष्ट सूची (@CodeCowboyOrg द्वारा दी गई) में जोड़ने के लिए जहां OPTION (RECOMPILE) बहुत मददगार हो सकती है,

  1. टेबल चर । जब आप तालिका चर का उपयोग कर रहे हैं, तो तालिका चर के लिए कोई पूर्व-निर्मित आँकड़े नहीं होंगे, अक्सर क्वेरी योजना में अनुमानित और वास्तविक पंक्तियों के बीच बड़े अंतर के लिए अग्रणी होता है। तालिका चर के साथ प्रश्नों पर विकल्प (रीकैपाइल) का उपयोग करने से एक क्वेरी योजना की पीढ़ी की अनुमति मिलती है जिसमें पंक्ति संख्याओं का बेहतर अनुमान होता है। मेरे पास तालिका चर का विशेष रूप से महत्वपूर्ण उपयोग था जो अनुपयोगी था, और जिसे मैं छोड़ने के लिए जा रहा था, जब तक कि मैंने विकल्प (रीकंपाइल) नहीं जोड़ा। रन का समय घंटे से बस कुछ ही मिनटों के लिए चला गया। यह शायद असामान्य है, लेकिन किसी भी मामले में, यदि आप तालिका चर का उपयोग कर रहे हैं और अनुकूलन पर काम कर रहे हैं, तो यह देखने लायक है कि क्या विकल्प (रीकंपाइल) फर्क करता है।

1
मेरे पास 5 टेबल चर के साथ एक क्वेरी है। मेरी मशीन पर यह आधे घंटे से अधिक समय तक चलता है। मेरे सह-कार्यकर्ता की मशीन पर यह <1 सेकंड में निष्पादित होता है। मशीनों में समान हार्डवेयर और समान SQL सर्वर संस्करण है। यदि हम दोनों OPTION (RECOMPILE) जोड़ते हैं तो यह दोनों मशीनों पर 2 सेकंड में निष्पादित होता है। सभी मामलों में निष्पादन परीक्षण एसएसएमएस में किया जाता है। इस अंतर का क्या कारण हो सकता है?
एडम

1
क्या आप अपनी मशीन पर और अपने सहकर्मियों की मशीन पर इसके लिए निष्पादन योजना की तुलना बिना विकल्प (recompile) के कर सकते हैं? यह अंतर का स्रोत दिखा सकता है।
DWright

1
अस्थायी तालिकाओं के लिए, यह एक ही स्थिति है?
मुफ्लिक्स

1
@ मुफ्लिक्स: अच्छा सवाल। मुझे विश्वास नहीं है कि प्रभाव अस्थायी तालिकाओं के लिए समान है, क्योंकि उनके पास आंकड़े हैं और इंजन को अन्य तालिकाओं की तरह स्वचालित पुन: चयन विकल्प बनाना चाहिए, मुझे विश्वास है (लेकिन मैं निश्चित नहीं हूं)। हो सकता है कि कोई और व्यक्ति अधिक निश्चितता के साथ जानता हो।
DW13

2
अस्थायी तालिकाओं में आँकड़े स्वचालित रूप से अद्यतन नहीं किए जाते हैं या पुन: व्यवस्थित किए जाते हैं ताकि प्रोग्रामर को ऐसा करने की आवश्यकता हो।
जे। माइकल वुएर्थ

1

प्रश्नों को ट्यूनिंग करने और अनुक्रमणिका और आँकड़ों को फिर से बनाने / पुन: निर्माण करने से पहले की गई पहली क्रिया, अन्य तरीके जो आप अपना समय बर्बाद कर रहे हैं।

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

एक उदाहरण के रूप: सूचकांक idx01_datafeed_trans datafeed_trans (feedid, feedDate) पर बनाने में शामिल हैं (acctNo, tradeDate)

यदि योजना स्थिर है या आप इसे स्थिर कर सकते हैं, तो आप निश्चित निष्पादन योजना को बचाने और उपयोग करने के लिए sp_executesql ('sql वाक्य') के साथ वाक्य को निष्पादित कर सकते हैं।

यदि योजना अस्थिर है, तो आपको हर बार एक निष्पादन योजना का मूल्यांकन करने और बनाने के लिए एक तदर्थ विवरण या EXEC ('sql वाक्य') का उपयोग करना होगा। (या एक संग्रहीत प्रक्रिया "recompile के साथ")।

आशा करता हूँ की ये काम करेगा।


1

इस सवाल पर नक़ल करना लेकिन एक स्पष्टीकरण है जिसे किसी ने भी नहीं माना है।

सांख्यिकी - आंकड़े उपलब्ध नहीं हैं या भ्रामक हैं

यदि निम्नलिखित में से सभी सत्य हैं:

  1. कॉलम फीडिड और फीडडेट को अत्यधिक सहसंबद्ध होने की संभावना है (जैसे कि फीड आईडी फीड तिथि की तुलना में अधिक विशिष्ट है और दिनांक पैरामीटर निरर्थक जानकारी है)।
  2. अनुक्रमिक कॉलम के रूप में दोनों स्तंभों के साथ कोई सूचकांक नहीं है।
  3. इन दोनों स्तंभों को कवर करने वाले मैन्युअल रूप से बनाए गए आँकड़े नहीं हैं।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.