अचानक संग्रहीत योजना के लिए धीमी निष्पादन योजना


15

मैं एक समस्या को समझने की कोशिश कर रहा हूँ जो हम SQL Server 2000 के साथ कर रहे हैं। हम एक मामूली लेन-देन की वेबसाइट हैं और हमारे पास एक संग्रहित खरीद है जिसे sp_GetCurrentTransactionsएक ग्राहक नाम, और दो दिनांक स्वीकार करता है।

अब तिथियों और ग्राहक के आधार पर, यह क्वेरी शून्य से अधिकतम पंक्तियों तक कुछ भी वापस कर सकती है।

समस्या: हमने जो अनुभव किया है, वह यह है कि अचानक हम Execution Timeout Expiredकिसी विशेष क्लाइंट के लिए कई त्रुटियां (आमतौर पर या समान) प्राप्त करेंगे, जबकि वे इस संग्रहित खरीद को अंजाम देने की कोशिश करेंगे। इसलिए हम क्वेरी की जांच करते हैं, इसे SSMS में चलाते हैं और पाते हैं कि इसमें 30 का समय लगता है। इसलिए हम स्टोर किए गए प्रोक और -बैंग को फिर से जोड़ते हैं- यह अब 300ms में चलता है।

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

मेरे सामने प्रस्तुत विकल्प चालित समस्या है जो संग्रहित खरीद से समस्या है और डायनेमिक एसक्यूएल में वापस है जिसके पास हर रन पर निष्पादन योजना है।

यह मेरे लिए एक कदम वापस की तरह महसूस करता है और मुझे लगता है कि इस के आसपास एक रास्ता होना चाहिए। क्या इस मुद्दे से निपटने का कोई और तरीका है?

किसी भी और सभी प्रतिक्रियाओं की सराहना की जाती है।


वहाँ एक अगर / कोई और बयान में proc है? मैंने यह देखा है जब योजना को स्टेटमेंट में कैश किया जाता है और फिर गलत प्लान का उपयोग करके दूसरे ब्लॉक के तहत निष्पादित करने की कोशिश करता है। क्या ये त्रुटियां खरीद में बदलाव के अनुरूप हैं?
जेरेमी ग्रे

@ जेरेमी: खरीद के लिए कोई बदलाव नहीं और कोई बयान नहीं / अगर बयान।
सियारन आर्चर

जवाबों:


14

इस समस्या को पैरामीटर सूँघना कहा जाता है।

SQL सर्वर के बाद के संस्करण आपको इससे निपटने के अधिक विकल्प प्रदान करते हैं जैसे कि OPTION (RECOMPILE)या OPTIMIZE FORसंकेत।

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

आम तौर पर सबसे भयावह रूप से खराब योजनाएं उन मापदंडों के लिए संकलित की जाती हैं जो बहुत ही उच्च चयनात्मकता वाले मापदंडों के लिए संकलित की जाती हैं, लेकिन कम चयनात्मकता वाले मापदंडों के साथ चलती हैं।

उत्पन्न योजना को इस दृष्टिकोण के साथ अधिक मजबूत और सभी पैरामीटर मानों के लिए संतोषजनक माना जाता है, तब जेएनके द्वारा सुझाए गए इस दृष्टिकोण का लाभ यह है कि यह हर कॉल के लिए एक संकलन लागत नहीं लेता है।

इसका नुकसान यह है कि कुछ निष्पादन के लिए समय विशेष रूप से उन पैरामीटर मानों के अनुरूप योजना के लिए अधिक से अधिक हो सकता है, इसलिए यह संकलन समय बनाम निष्पादन समय का व्यापार बंद है।


3
या ओरेकल शब्दावली में "बाइंड पीकिंग"
गेयस

धन्यवाद @Gaius, एक से अधिक RDBMS के लिए शब्दावली जानने के लिए अच्छा;)
आंद्रेई Reanea

6

डायनेमिक एसक्यूएल का उपयोग करने के बजाय, आप हमेशा अपनी कॉल को बदल सकते हैं:

EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE

WITH RECOMPILEबलों (आपने ठीक समझा!) कार्य योजना लागू करके जब भी यह चलाया जाता है की एक पुनः संकलित करें।

आप WITH RECOMPILEसंग्रहीत खरीद की परिभाषा में भी शामिल कर सकते हैं :

CREATE PROCEDURE usp.MyProcedure (Parameters)
WITH RECOMPILE
AS
...

2

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

तकनीक यह है - संग्रहीत कार्यविधि को 2 में तोड़ें, एक का अर्थ है मापदंडों के एक सेट के लिए, दूसरे के लिए एक। प्रत्येक खंड को ऐसे जोड़ें जहां उनके बीच वे सभी संभावित मामलों को कवर करें। क्वेरी योजनाओं को देखें - एक को मापदंडों के एक सेट के लिए अनुकूलित किया जाना चाहिए, दूसरे सेट के लिए। ऐसा होने के लिए आपको क्वेरी के साथ छेड़छाड़ करनी पड़ सकती है, या आपकी क्वेरी के लिए इसे प्राप्त करना संभव नहीं हो सकता है, जिस स्थिति में यह दृष्टिकोण काम नहीं करेगा।

अब अपनी मूल संग्रहीत प्रक्रिया को पैरामीटर मान की जाँच करें और पिछले पैराग्राफ से दो संग्रहीत प्रक्रियाओं में से एक को भेजें।

यह काम कर सकता है, लेकिन यह ऑप्टिमाइज़र को आपकी क्वेरी के लिए अधिक प्रभावी ढंग से काम करने के लिए मजबूर करने के लिए एक हैक की तरह है। ऐसे सभी हैक की तरह, डेटाबेस के भविष्य के संस्करणों में यह अनावश्यक हो सकता है या यहां तक ​​कि चीजों को खराब कर सकता है। यहां तक ​​कि अगर यह काम करता है तो आपको यह तय करना होगा कि क्या यह इसके लायक है।


1

आप SET FORCEPLANसंकेत भी कर सकते हैं ।

http://msdn.microsoft.com/en-us/library/ms188344.aspx
यह मूल रूप से आपको यह चुनने की अनुमति देता है कि ज्वाइन क्या होता है।

आपके पास यह सुनिश्चित करने के लिए सूचकांक संकेत हो सकते हैं कि SQL सर्वर सही अनुक्रमित का उपयोग करता है।


0

हम्मम ... अगर हम सिर्फ इस एक संग्रहीत प्रक्रिया पर ध्यान केंद्रित कर रहे हैं, तो मुझे आश्चर्य होगा कि कैश्ड निष्पादन योजना का उपयोग करने से आप जिस मुद्दे को देख रहे हैं, वह हो जाएगा। मैं ग्राहक और दो तारीखों के लिए मापदंडों के एक सेट का उपयोग करके संग्रहीत प्रक्रिया के निष्पादन की योजना को देखने के लिए कहूंगा। मुझे आश्चर्य है कि क्या एक अधिक विशिष्ट सूचकांक उपयोगी होगा -> जैसे कि customerId पर, और केवल दो तिथियां?


2
आश्चर्य क्यों? पैरामीटर सूँघना इन लक्षणों के साथ एक काफी सामान्य मुद्दा है और ऐसा लगता है जैसे कि समस्या के रूप में डीबीए ने पहचान की है।
मार्टिन स्मिथ

@MartinSmith - मुझे थोड़ा आश्चर्य है कि डीबीए जो परमवीर सूँघने के बारे में जानता है, वह पुनर्मूल्यांकन के संकेतों के बारे में नहीं जानता है ...
जेएनके

@ जेएनके - यह सच है। निश्चित नहीं कि वे इसका उल्लेख क्यों नहीं करेंगे।
मार्टिन स्मिथ

0

अचानक अपमानजनक प्रदर्शन एक अक्षम क्वेरी योजना की तरह लगता है, जो संभवतः लापता आँकड़ों के परिणामस्वरूप होता है। "त्रुटियों और चेतावनियों" ईवेंट श्रेणियों के साथ एक SQL सर्वर प्रोफाइलर सेट करें और देखें कि क्या लापता आँकड़ों के बारे में चेतावनी है।

आपको एक इंडेक्स भी याद आ रहा होगा, या हो सकता है कि आपको इंडेक्स को डीफ़्रैग करने की आवश्यकता हो क्योंकि वे SQL सर्वर का उपयोग करने के लिए बहुत अधिक खंडित हो सकते हैं, जिसके परिणामस्वरूप यह सोचकर कि टेबल स्कैन कम I / O का उत्पादन करेगा।

@JKK संग्रहीत प्रोक्स के बारे में एक शानदार बिंदु उठाता है - ये संकलित अपफ्रंट प्राप्त करते हैं और क्वेरी योजना संग्रहीत प्रक्रिया के साथ संग्रहीत की जाएगी।

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

इसलिए, संक्षेप में:

  1. लापता आँकड़ों की जाँच करें
  2. सूचकांक विखंडन की जाँच करें
  3. एक संग्रहीत खरीद बनाएं और उपयोग करें
  4. कृपया खरीद का नाम बदलें - sp_ आंतरिक सिस्टम SQL सर्वर procs के लिए एक नरम आरक्षित उपसर्ग नामस्थान है - जिसके परिणामस्वरूप SQL सर्वर हमेशा उन संग्रहीत प्रक्रियाओं के लिए मास्टर डेटाबेस में दिखता है। Sp_ के बजाय proc usp_ का नाम बदलने से प्रदर्शन में वृद्धि होगी, लेकिन मुझे इस मामले में आपकी समस्या पर संदेह है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.