SQL सर्वर - यदि संग्रहीत कार्यविधि और योजना कैश में तर्क


15

SQL सर्वर 2012 और 2016 मानक:

अगर मैं if-elseएक पैरामीटर के मान के आधार पर कोड की दो शाखाओं में से एक को निष्पादित करने के लिए संग्रहीत कार्यविधि में तर्क रखता हूं , तो क्या इंजन नवीनतम संस्करण को कैश करता है?

और यदि निम्नलिखित निष्पादन पर, पैरामीटर का मूल्य बदल जाता है, तो क्या यह संग्रहीत प्रक्रिया को फिर से संकलित और फिर से संचय करेगा , क्योंकि कोड की एक अलग शाखा को निष्पादित किया जाना चाहिए? (यह प्रश्न संकलन के लिए काफी महंगा है।)

जवाबों:


27

SQL सर्वर 2012 और 2016 मानक: यदि मैं एक पैरामीटर के मान के आधार पर कोड की दो शाखाओं में से एक को निष्पादित करने के लिए संग्रहीत प्रक्रिया में if-else तर्क रखता हूं, तो इंजन नवीनतम संस्करण को कैश करता है?

नहीं, यह सभी संस्करणों को कैश करता है। या यों कहें, यह खोजे गए सभी रास्तों के साथ एक संस्करण को कैश करता है , जिसे चर में पारित किया जाता है।

स्टैक ओवरफ्लो डेटाबेस का उपयोग करते हुए यहां एक त्वरित डेमो दिया गया है।

एक सूचकांक बनाएँ:

CREATE INDEX ix_yourmom ON dbo.Users (Reputation) INCLUDE (Id, DisplayName);
GO 

एक इंडेक्स हिंट के साथ एक संग्रहीत कार्यविधि बनाएं जो एक इंडेक्स को इंगित करता है जो मौजूद नहीं है, ब्रंचेड कोड में।

CREATE OR ALTER PROCEDURE dbo.YourMom (@Reputation INT)
AS 
BEGIN

    IF @Reputation = 1
    BEGIN
        SELECT u.Id, u.DisplayName, u.Reputation
        FROM dbo.Users AS u WITH (INDEX = PK_Users_Id)
        WHERE u.Reputation = @Reputation;
    END;

    IF @Reputation > 1
    BEGIN
        SELECT u.Id, u.DisplayName, u.Reputation
        FROM dbo.Users AS u WITH (INDEX = ix_yourdad)
        WHERE u.Reputation = @Reputation;

    END;

END;

यदि मैं उस संग्रहित खरीद को निष्पादित करता हूं जो प्रतिष्ठा = 1 की तलाश में है, तो मुझे एक त्रुटि मिलती है।

EXEC dbo.YourMom @Reputation = 1;

Msg 308, लेवल 16, स्टेट 1, प्रोसीजर योरमॉम, लाइन 14 [बैच स्टार्ट लाइन 32] इंडेक्स 'ix_yourdad' टेबल पर 'dbo.Users' (FROM क्लॉज में निर्दिष्ट) मौजूद नहीं है।

यदि हम सूचकांक नाम को ठीक करते हैं और क्वेरी को फिर से चलाते हैं, तो कैश्ड प्लान इस तरह दिखता है:

पागल

अंदर, एक्सएमएल के @Reputationचर के दो संदर्भ होंगे ।

<ColumnReference Column="@Reputation" ParameterDataType="int" ParameterCompiledValue="(1)" />

थोड़ा सा सरल परीक्षण केवल संग्रहीत खरीद के लिए एक अनुमानित योजना प्राप्त करना होगा। आप ऑप्टिमाइज़र को दोनों रास्तों की खोज करते हुए देख सकते हैं:

पागल

और अगर निम्नलिखित निष्पादन पर, पैरामीटर का मूल्य बदल जाता है, तो क्या यह संग्रहीत प्रक्रिया को फिर से संकलित और फिर से कैश करेगा, क्योंकि कोड की एक अलग शाखा को निष्पादित किया जाना चाहिए? (यह प्रश्न संकलित करने के लिए काफी महंगा है।) धन्यवाद

नहीं, यह पहले संकलन के रनटाइम मूल्य को बनाए रखेगा।

यदि हम किसी भिन्न के साथ पुन: निष्पादित करते हैं @Reputation:

EXEC dbo.YourMom @Reputation = 2;

से वास्तविक योजना :

<ColumnReference Column="@Reputation" ParameterDataType="int" ParameterCompiledValue="(1)" ParameterRuntimeValue="(2)" />

हमारे पास अभी भी 1 का संकलित मूल्य है, लेकिन अब 2 का रनटाइम मान है।

प्लान कैश में, जिसे आप फ्री टूल के साथ देख सकते हैं जैसे मेरी कंपनी विकसित करती है, sp_BlitzCache :

पागल

संग्रहीत प्रक्रिया को दो बार बुलाया गया है, और इसमें प्रत्येक कथन को एक बार बुलाया गया है।

तो हमारे पास क्या है? संग्रहीत प्रक्रिया में दोनों प्रश्नों के लिए एक कैश्ड योजना।

यदि आप चाहते हैं शाखायुक्त तर्क की इस तरह, आप उप संग्रहित प्रक्रियाओं कॉल करने के लिए होगा:

CREATE OR ALTER PROCEDURE dbo.YourMom (@Reputation INT)
AS 
BEGIN

    IF @Reputation = 1
    BEGIN

        EXEC dbo.Reputation1Query;

    END;

    IF @Reputation > 1
    BEGIN

        EXEC dbo.ReputationGreaterThan1Query;

    END;

END;

या गतिशील एसक्यूएल:

DECLARE @sql NVARCHAR(MAX) = N''

SET @sql +=
N'
SELECT u.Id, u.DisplayName, u.Reputation
        FROM dbo.Users AS u '
IF @Reputation = 1
BEGIN
    SET @sql += N' (INDEX = PK_Users_Id)
        WHERE u.Reputation = @Reputation;'
END;


IF @Reputation > 1 
BEGIN

SET @sql += ' WITH (INDEX = ix_yourmom)
        WHERE u.Reputation = @Reputation;'

END;


EXEC sys.sp_executesql @sql;

उम्मीद है की यह मदद करेगा!

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