2014-10-10 9 views
7

मैं वर्षों से कोल्डफ्यूजन/एमएस एसक्यूएल पर काम कर रहा हूं और यह मैंने देखा है कि सबसे अजीब समस्याओं में से एक है। समस्या को हल कर लिया गया है लेकिन मुझे वास्तव में समझ में नहीं आया कि क्या हुआ; यह सवाल संभावित कारण का स्पष्ट विचार प्राप्त करने का प्रयास कर रहा है।धीमी चल रही क्वेरी, सीएफ 9 और एमएसएसक्यूएल 2008; भ्रष्ट निष्पादन योजना?

समस्या

एक स्थिर उत्पादन वातावरण में, कोई स्पष्ट कारण के लिए, एक क्वेरी (के बारे में 10 बार सामान्य की तुलना में धीमी) के चारों ओर 1,000-1,500 एमएस में लौटने लगता है। मैं इस के लिए यह अलग करने में सक्षम था:

<cfquery datasource="#ds#" name="query"> 
    select 1 
    from eLearning.v_courseCompletion cc 
    where 
     cc.memberIncId = <cfqueryparam value="3" cfsqltype="cf_sql_integer"> and 
     cc.courseId = <cfqueryparam value="25" cfsqltype="cf_sql_integer"> and 
     cc.currentCourseCompleted = 1 
</cfquery> 

क्या अजीब बात है, है इस व्यवहार जब एक पाश के भीतर बिगड़ जाती है, यहाँ तक कि जब एक एकल पुनरावृत्ति वहाँ, इस उदाहरण की तरह:

<cfloop from="1" to="1" index="i"> 
    <cfquery datasource="#ds#" name="query"> 
     select 1 
     from eLearning.v_courseCompletion cc 
     where 
     cc.memberIncId = <cfqueryparam value="3" cfsqltype="cf_sql_integer"> and 
     cc.courseId = <cfqueryparam value="25" cfsqltype="cf_sql_integer"> and 
     cc.currentCourseCompleted = 1 
    </cfquery> 
</cfloop> 

यह बिल्कुल ऊपर जैसा ही होना चाहिए, है ना? लूप का कोई प्रभाव नहीं होना चाहिए, बल्कि इसके बजाय, यह परीक्षण लगभग 10 गुना धीमा हो जाता है, जो 7,000-16,000 एमएस के बीच में लौटता है। इस तरह समस्या का पता चला था; क्वेरी (एक ऑब्जेक्ट विधि के भीतर दफन) को लूप के शरीर से बुलाया जा रहा था, अगर लूप 5 या 6 गुना से अधिक बार अनुरोध करता है तो अनुरोध समय-समय पर होगा।

मेरे लिए, इसने कोल्डफ्यूजन पक्ष पर एक समस्या का संकेत दिया लेकिन सेवा को फिर से शुरू करने, या वास्तव में मशीन ने कुछ भी नहीं किया।

इस बीच, एक बार अलग हो जाने पर, मैंने देखा कि क्वेरी में कोई भी बदलाव करने से प्रदर्शन 150-190 एमएस के आसपास अपेक्षित स्तर पर लौट आया। उदाहरण के लिए:

  • चयनित फ़ील्ड (। यानी select *)
  • तालिका उर्फ ​​निकाला जा रहा है बदल रहा है (cc)
  • एक इनलाइन मूल्य
  • से कोई भी शर्त निकाला जा रहा है के साथ या तो <cfqueryparam> की जगह

इनमें से कोई भी परिवर्तन समस्या को "निश्चित" करता है, लेकिन मूल क्वेरी चलाते समय, प्रदर्शन समस्या वापस आ जाएगी।

समाधान

इस बिंदु पर मैं अनुमान लगाया क्वेरी के निष्पादन योजना दूषित हो गया था या कुछ और, some Googling किया था, और डीबी सर्वर के विरुद्ध DBCC FREEPROCCACHE भाग गया। यह तुरंत समस्या को ठीक किया गया। बढ़िया है, समस्या हल ....

प्रश्न

तो हालांकि बाद से, मैं थोड़ा और अधिक शोध किया है और आम सहमति है कि निष्पादन की योजना "भ्रष्ट नहीं मिलता" हो रहा है। some talksimilar problems संग्रहीत प्रक्रियाओं और parameter sniffing के साथ होता है लेकिन मैं यहां किसी भी एसपी का उपयोग नहीं कर रहा हूं। हम नेस्टेड जॉइन के साथ काफी जटिल दृश्य से चयन कर रहे हैं (eLearning.v_courseCompletion)। क्या यह मुद्दा है?

असल में, वास्तव में यहां क्या हुआ? मैं इसे फिर से होने से कैसे रोकूं?

.. और सीएफ में लूप का कनेक्शन क्या है?!

संस्करण

  • Coldfusion 9.0.2.282541 (64 बिट)
  • SQL सर्वर एक्सप्रेस 10.50.4297 (64 बिट)
  • दोनों सर्वर जीत सर्वर हैं 2008 R2 डेटासेंटर (64 बिट)

उत्तर

6

जब आप एक cfqueryparam का उपयोग करते हैं तो आप हुड के नीचे एक संग्रहीत प्रक्रिया का उपयोग कर रहे हैं। जब आप cfqueryparam का उपयोग नहीं करते हैं, तो आपकी क्वेरी को केवल "मुक्त टेक्स्ट" बैच क्वेरी के रूप में भेजा जाता है। जब आप cfqueryparam का उपयोग करते हैं, तो आप sp_executeSQL() का उपयोग करके निष्पादित करने के लिए अपनी क्वेरी भेज रहे हैं जो स्वयं ही आपके क्वेरी बॉडी को पैरामीटर के रूप में भेज देगा। यह क्वेरी योजना को कैश करने की अनुमति देता है। यदि यह वही क्वेरी देखता है, तो वह उस विशेष योजना के लिए सहेजे गए आंकड़ों का उपयोग करेगा। इसका मतलब यह है कि अगर यह वास्तव में कुछ अजीब डेटा के साथ भाग गया और क्वेरी को निष्पादित करने के लिए एक बुरा विचार मिला, तो अगले पुनरावृत्तियों में सभी एक ही योजना का उपयोग करेंगे, जो इस क्वेरी के 99% उपयोग मामलों के लिए "खराब योजना" है, लेकिन शायद उस एक oddball उदाहरण के लिए एक अच्छी योजना है।

sp_execute SQL के साथ निष्पादित प्रत्येक क्वेरी भी एक संख्यात्मक हैंडल देता है जो जेडीबीसी ड्राइवर केवल एसक्यूएल को बताने के लिए उपयोग कर सकता है जो मूल रूप से शॉर्टकट का उपयोग कर सकता है। इसे CFDmin में आपकी डीएसएन सेटिंग्स में "अधिकतम पूल किए गए बयान" कहा जाता है। 0 या 1000 पर सेट होने से इस तथ्य को प्रभावित नहीं होता है कि आप sp_executeSQL के साथ एक योजना कैश का लाभ उठाएंगे।

http://blogs.msdn.com/b/turgays/archive/2013/09/18/exec-vs-sp-executesql.aspx

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

+0

आह शानदार, जो बहुत समझ में आता है। किसी लूप (यहां तक ​​कि 1 पुनरावृत्ति) के भीतर से इसे चलाने में कोई अंतर्दृष्टि प्रदर्शन को प्रभावित करेगी? धन्यवाद – Molomby

+0

नहीं, लूप अपराधी की तरह नहीं लगता है। मैं कुछ अन्य परिस्थितियों को दोष दूंगा जो लूप प्रदान करता है, जैसे इंडेक्स वैरिएबल या लूप बनाने वाला कुछ ऐसा लगता है जैसे इसे दोष देना है। इसके अलावा, आप लगभग हमेशा लूप में cfquery नहीं चलने से दूर हो सकते हैं। बहुत कम समय होते हैं जब यह वास्तव में समझ में आता है। –

+0

फॉलो अप के लिए धन्यवाद लेकिन मैं आपको आश्वासन देता हूं कि लूप में कुछ और नहीं है जो इसे (कारण होना चाहिए); उपरोक्त पोस्ट कोड ब्लॉक सीधे मेरे परीक्षण मामलों से बाहर हैं (साथ ही 'getTickCount()' पहले और बाद में)। लूप के इंडेक्स (या आइटम) वैरिएबल को क्वेरी द्वारा बिल्कुल संदर्भित नहीं किया गया है और लूप बॉडी में और कुछ नहीं है। शायद जावा के लूप संकलन के दौरान कुछ चल रहा है? अगर मैं इस मुद्दे को पुन: पेश कर सकता हूं तो मैं थोड़ा गहरा खोदूंगा। – Molomby

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