2013-05-29 5 views
15

मैं एसक्यूएल सर्वर 2008 R2 पर एक संग्रहीत प्रक्रिया के साथ एक बहुत ही अजीब मुद्दा है। कभी-कभी, हर महीने लगभग एक बार, मेरे पास एक प्रक्रिया है जो बहुत धीमी हो जाती है, कुछ मिलीसेकंड के बजाए चलाने के लिए लगभग 6sec लगती है। लेकिन अगर मैं इसे कुछ भी बदले बिना इसे फिर से संकलित करता हूं, तो यह फिर से चलता है। यह सभी संग्रहीत प्रक्रियाओं पर नहीं होता है, केवल एक (सर्वर पर कुछ सैकड़ों हैं)।संग्रहित प्रक्रिया तेजी के बाद पुन: संयोजित रन

मेरा अनुमान है जब एसपी संकलित किया गया है है, यह कैश किया गया है और यह कैश हर बार जब मैं इसे कहते पुन: उपयोग किया है, और यह कैश्ड संस्करण किसी कारण से दूषित हो जाता है।

मैं शायद कुछ लोगों को आशा व्यक्त की पहले से ही इस मुद्दे को इस तरह का सामना करना पड़ा, या कम से कम, सही दिशा में मुझे बिंदु सकता है SQL सर्वर या आईआईएस किस विन्यास संग्रहीत प्रक्रिया कैश को प्रभावित कर सकता है?

कोड यह रहा:

USE [MyBaseName] 
GO 
/****** Object: StoredProcedure [dbo].[Publication_getByCriteria] Script Date: 05/29/2013 12:11:07 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[Publication_getByCriteria] 
    @id_sousTheme As int = null, 
    @id_theme As int = null, 
    @nbPubli As int = 1000000, 
    @bActuSite As bit = null, 
    @bActuPerso As bit = null, 
    @bActuNewsletter As bit = null, 
    @bActuChronique As bit = null, 
    @bActuVideo As bit = null, 
    @bActuVideoBuzz As bit = null, 
    @bActuOpportunite As bit = null, 
    @id_contact As int = null, 
    @bOnlyPublished As bit = 0, 
    @bOnlyForHomePage as bit = 0, 
    @id_contactForTheme As int = null, 
    @id_newsletter As int = null, 
    @ID_ActuChronique As int = null, 
    @sMotClef As varchar(500) = null, 
    @sMotClefForFullText as varchar(500) = '""', 
    @dtPublication As datetime = null, 
    @bParlonsFinance As bit = null, 
    @bPartenaires as bit = null, 
    @bUne As bit = null, 
    @bEditoParlonsFinance As bit = null, 
    @bEditoQuestionFonds as bit = null, 
    @dtDebPublication As datetime = null, 
    @dtFinPublication As datetime = null, 
    @bOnlyActuWithDroitReponse As bit = 0, 
    @bActuDroitReponse As bit = null 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @dtNow As datetime 
    SET @dtNow = GETDATE() 

    SELECT TOP (@nbPubli) p.id_publication, p.sTitre, p.sTexte, p.sTexteHTML, p.dtPublication, p.id_linkedDroitReponse, 
     si.id_actusite, pe.id_actuPerso, ne.id_actuNewsletter, ac.id_actuChronique, av.id_actuVideo, ap.id_actuOpportunite, ad.id_actuDroitReponse, 
     c.ID_Contact, c.sPhotoCarre, NULL As sTypePubli, n.id_newsletter, 
     dbo.Publication_get1Theme(p.id_publication) As theme, 
     CAST(CASE WHEN ad.id_actuDroitReponse IS NULL THEN 0 ELSE 1 END As bit) As bIsDroitReponse, 
     coalesce(Personne.sNom, Societe.sNom) as sNom, Personne.sPrenom 
    FROM Publication p 
     LEFT OUTER JOIN ActuSite si ON p.id_publication = si.id_publication 
     LEFT OUTER JOIN ActuPerso pe ON p.id_publication = pe.id_publication 
     LEFT OUTER JOIN ActuNewsletter ne ON p.id_publication = ne.id_publication 
     LEFT OUTER JOIN ActuChronique ac ON p.id_publication = ac.id_publication 
     LEFT OUTER JOIN ActuVideo av ON p.id_publication = av.id_publication 
     LEFT OUTER JOIN ActuOpportunite ap ON p.id_publication = ap.id_publication 
     LEFT OUTER JOIN ActuDroitReponse ad ON p.id_publication = ad.id_publication 
     LEFT OUTER JOIN Contact c ON p.id_contact = c.ID_Contact 
     LEFT OUTER JOIN Personne ON Personne.id_contact = c.id_contact 
     LEFT OUTER JOIN Societe ON Societe.id_contact = c.id_contact 
     LEFT OUTER JOIN Newsletter n ON ne.id_actuNewsletter = n.id_actuNewsletter 
    WHERE p.bSupp = 0 
    AND (@bOnlyPublished = 0 Or (@bOnlyPublished = 1 AND p.dtPublication IS NOT NULL AND p.dtPublication < @dtNow)) 
    AND (@id_sousTheme IS NULL Or p.id_publication IN(SELECT id_publication FROM PubliSousTheme WHERE id_soustheme = @id_sousTheme)) 
    AND (@id_theme IS NULL Or p.id_publication IN(SELECT id_publication FROM PubliTheme WHERE id_theme = @id_theme)) 
    AND ((@bActuSite = 1 AND si.id_actusite IS NOT NULL) 
      OR (@bActuPerso = 1 AND pe.id_actuPerso IS NOT NULL) 
      OR (@bActuNewsletter = 1 AND ne.id_actuNewsletter IS NOT NULL) 
      OR (@bActuChronique = 1 AND ac.id_actuChronique IS NOT NULL) 
      OR (@bActuVideo = 1 AND av.id_actuVideo IS NOT NULL) 
      OR (@bActuVideoBuzz = 1 AND av.id_actuVideo IS NOT NULL and coalesce(av.sBuzz, '') <> '') 
      OR (@bActuOpportunite = 1 AND ap.id_actuOpportunite IS NOT NULL) 
      OR (@bActuDroitReponse = 1 AND ad.id_actuDroitReponse IS NOT NULL)) 
    AND (@id_contact IS NULL Or p.id_contact = @id_contact) 
    AND (@id_contactForTheme IS NULL Or 
      (p.id_publication IN(SELECT id_publication FROM PubliSousTheme 
       WHERE id_soustheme IN(SELECT id_soustheme FROM ContactSousTheme WHERE id_contact = @id_contactForTheme))) 
      Or (p.id_publication IN(SELECT id_publication FROM PubliTheme 
       WHERE id_theme IN(SELECT id_theme FROM ContactTheme WHERE id_contact = @id_contactForTheme))) 
      ) 
    AND (@ID_ActuChronique is NULL or id_actuChronique = @ID_ActuChronique) 
    AND (@id_newsletter IS NULL Or p.id_publication IN(SELECT id_publication FROM ListActuNewsletter WHERE id_newsletter = @id_newsletter)) 
    AND (@sMotClef IS NULL 
     or contains((p.sTexte, p.sTitre), @sMotClefForFullText) 
     Or Personne.sNom LIKE '%' + @sMotClef + '%' COLLATE Latin1_General_CI_AI 
     Or Personne.sPrenom LIKE '%' + @sMotClef + '%' COLLATE Latin1_General_CI_AI 
     Or Societe.sNom LIKE '%' + @sMotClef + '%' COLLATE Latin1_General_CI_AI 
     ) 
    AND (@dtPublication IS NULL Or p.dtPublication >= @dtPublication) 
    AND (
     @bParlonsFinance IS NULL Or 
     (@bParlonsFinance = 0 AND p.id_publication NOT IN(SELECT id_publication FROM PubliTheme 
       WHERE id_theme IN(SELECT id_theme FROM Theme WHERE bParlonsFinance = 1))) 
     Or (@bParlonsFinance = 1 AND p.id_publication IN(SELECT id_publication FROM PubliTheme 
       WHERE id_theme IN(SELECT id_theme FROM Theme WHERE bParlonsFinance = 1)))) 
    AND (
     @bPartenaires IS NULL Or 
     (@bPartenaires = 0 AND p.id_publication NOT IN(SELECT id_publication FROM PubliTheme 
       WHERE id_theme IN(SELECT id_theme FROM Theme WHERE 0 = 1))) 
     Or (@bPartenaires = 1 AND p.id_publication IN(SELECT id_publication FROM PubliTheme 
       WHERE id_theme IN(SELECT id_theme FROM Theme WHERE 0 = 1)))) 
    AND (
     @bUne IS NULL 
     Or p.bUne = @bUne) 
    AND (@bEditoParlonsFinance IS NULL 
     Or p.bEditoParlonsFinance = @bEditoParlonsFinance) 
     AND (@bEditoQuestionFonds IS NULL 
     Or p.bEditoQuestionFonds = @bEditoQuestionFonds) 
    AND (@dtDebPublication IS NULL Or p.dtPublication >= @dtDebPublication) 
    AND (@dtFinPublication IS NULL Or p.dtPublication <= @dtFinPublication) 
    AND (@bOnlyActuWithDroitReponse = 0 Or (@bOnlyActuWithDroitReponse = 1 AND p.id_linkedDroitReponse IS NOT NULL)) 
    and (@bOnlyForHomePage = 0 or (@bOnlyForHomePage = 1 and ac.bHomePage = 1)) 
    ORDER BY coalesce(p.dtPublication, p.dtCreate) DESC, p.id_publication DESC 
END 
+0

देखें कि यह मदद करता है .. http://msdn.microsoft.com/en-us/library/ms190439(v=sql.105).aspx – Elmer

उत्तर

23

जब आप पहली बार एक संग्रहीत प्रक्रिया संकलन, इसके निष्पादन योजना कैश की गई हो जाता है।

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

इससे बचने का एक तरीका CREATE PROCEDURE कथन के साथ RECOMPILE खंड शामिल करना है।

उदाहरण:

CREATE PROCEDURE dbo.mySpro 
@myParam 
WITH RECOMPILE 
AS 
BEGIN 
-- INSERT WORKLOAD HERE 
END 
GO 

ऐसा करने से, एक नई योजना हर बार प्रक्रिया कहा जाता है उत्पन्न हो जाएगा। यदि recompile time < time lost by its using the wrong cached plan, इस WITH RECOMPILE का उपयोग कर के लायक है। आपके मामले में, यह आपको हर बार जब आप नोटिस करते हैं कि धीरे-धीरे निष्पादित हो रहा है, तो यह प्रक्रिया को मैन्युअल रूप से पुन: संकलित करने के लिए आवश्यक समय/योजना को भी बचाएगा।

+1

यदि हम आवेदन के माध्यम से निष्पादित करते समय हर बार एक प्रक्रिया को दोबारा तैयार करते हैं, क्या यह प्रदर्शन को प्रभावित करता है? –

+0

धन्यवाद। मेरे लिए काम किया मैं फस गयी थी। एसक्यूएल 2012 ठीक काम करता है। लेकिन एसक्यूएल 2008 सर्वर काम नहीं कर रहा है। यह मुझे बचाया ... –

2

कई पैरामीटर के साथ संग्रहीत प्रक्रिया के लिए, क्वेरी के अंत में OPTION(OPTIMIZE FOR UNKNOWN) जोड़ने के लिए बुद्धिमान होगा ताकि संकलक को विशिष्ट पैरामीटर के लिए निष्पादन योजना को अनुकूलित न किया जा सके।

क्या एसक्यूएल सर्वर पहली बार यह एक संग्रहीत प्रक्रिया चलाता पैरामीटर है कि यह करने के लिए पारित किए गए के लिये कार्य योजना (रों) अनुकूलन है करता है। यह एक प्रक्रिया में किया जाता है जिसे Parameter Sniffing कहा जाता है।

सामान्य में, निष्पादन की योजना एसक्यूएल सर्वर द्वारा कैश कर रहे हैं ताकि एसक्यूएल सर्वर एक ही क्वेरी के लिए हर बार पुन: संयोजित करने के लिए नहीं है। अगली बार प्रक्रिया चलने पर, SQL सर्वर इसमें क्वेरी के लिए निष्पादन योजना का पुन: उपयोग करेगा ... हालांकि, यदि आप संग्रहीत प्रक्रिया को विभिन्न मानकों के साथ कॉल करते हैं तो निष्पादन योजना पूरी तरह से अक्षम हो सकती है।

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

अज्ञात

लिए

अनुकूलन सभी स्थानीय चर के लिए प्रारंभिक मान के स्थान पर सांख्यिकीय आंकड़ों का उपयोग करने के लिए जब क्वेरी संकलित और अनुकूलित है, जबरन parameterization के साथ बनाया मापदंडों सहित क्वेरी अनुकूलक का निर्देश देता है: documentation से।

@sion_corn से जवाब की सिफारिश संग्रहीत प्रक्रिया परिभाषा को WITH RECOMPILE जोड़ने, लेकिन इस पूरे बयान हर बार संग्रहीत प्रक्रिया निष्पादित किया जाता है की एक recompile बाध्य करती है। प्रक्रिया को अक्सर कहा जाता है तो यह एक अस्वीकार्य ओवरहेड हो सकता है।

+1

हैलो, मेरे पास एक संग्रहीत प्रक्रिया है जो SQL सर्वर से निष्पादित 3 से कम लेता है, और कभी भी पूर्ण पैरामीटर के साथ इकाई फ्रेमवर्क से निष्पादित (बहुत उच्च CPU उपयोग के साथ) पूरा नहीं करता है। डीबीसीसी ड्रॉप्लेनबफर्स ​​और डीबीसीसी फ्रीप्रोकैच निष्पादित करने से समस्या साफ हो जाती है। रिकॉम्प्ली के साथ जोड़ना भी काम करता है। लेकिन अगर मैं आपके सुझाव का पालन करता हूं, तो एसपी पूर्ण होने के साथ-साथ कुछ सेकंड लगते हैं। तो मेरे लिए, भले ही मैंने आपका जवाब ऊपर उठाया (मुझे अज्ञात के लिए ऑप्टिमाइज़ नहीं पता था), रिकॉम्प्ली के साथ सबसे अच्छा विकल्प प्रतीत होता है क्योंकि यह सर्वोत्तम प्रदर्शन देता है। – AFract

+0

@ अफ़्रैक्ट वास्तव में, 'रिकॉम्प्ली' के साथ 'अनन्य के लिए ऑप्टिमाइज़' से बेहतर हो सकता है, जहां विशिष्ट पैरामीटर के लिए निष्पादन योजना ऑप्टिमाइज़ेशन द्वारा रीकंपाइल ओवरहेड से अधिक है। –

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