अनुक्रमणिका SEEK का उपयोग तब तक नहीं किया जाता है जब तक कि विकल्प (RECOMPILE) नहीं होता है?


11

(एसओ से सवाल किया गया)

मेरे पास एक तालिका (डमी डेटा) है जिसमें गुच्छेदार सूचकांक में 2 कॉलम हैं:

यहाँ छवि विवरण दर्ज करें

अब मैं उन दो प्रश्नों को चलाता हूं:

declare 
@productid int =1 , 
@priceid  int = 1




SELECT productid,
       t.priceID
FROM   Transactions AS t
WHERE  (productID = @productid OR @productid IS NULL)
       AND (priceid = @priceid OR @priceid IS NULL)  


SELECT productid,
       t.priceID
FROM   Transactions AS t
WHERE  (productID = @productid)
       AND (priceid = @priceid)

दोनों प्रश्नों के लिए वास्तविक निष्पादन योजना है:

यहाँ छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं, पहला व्यक्ति SCAN का उपयोग कर रहा है जबकि दूसरा एक SEEK का उपयोग कर रहा है।

हालांकि - OPTION (RECOMPILE)पहली क्वेरी में जोड़कर , SEEK का उपयोग करने के लिए निष्पादन योजना भी बनाई:

यहाँ छवि विवरण दर्ज करें

DBA चैट पर दोस्तों ने मुझे बताया कि:

आपकी क्वेरी में, @ productid = 1, जिसका अर्थ है कि (productID = @ productID या @productID IS NULL) को (productID = @ productID) सरल बनाया जा सकता है। पूर्व में @productID के किसी भी मूल्य के साथ काम करने के लिए एक स्कैन की आवश्यकता होती है, बाद वाला एक तलाश का उपयोग कर सकता है। इसलिए, जब आप RECOMPILE का उपयोग करते हैं, तो SQL सर्वर आपको वास्तव में @productID में किस मूल्य पर दिखेगा और इसके लिए सबसे अच्छी योजना बनाता है। @ProductID में एक गैर-शून्य मान के साथ, एक तलाश सबसे अच्छा है। यदि @productID का मान अज्ञात है, तो योजना को @productID में किसी भी संभावित मान के अनुरूप होना चाहिए, जिसके लिए स्कैन की आवश्यकता होगी। सावधान रहें: विकल्प (रीकैपाइल) हर बार जब आप इसे चलाते हैं, तो योजना की एक पुनरावृत्ति होगी, जो हर निष्पादन में कुछ मिलीसेकंड जोड़ देगा। हालांकि यह केवल एक समस्या है अगर क्वेरी बहुत बार चलती है।

इसके अलावा:

यदि @productID शून्य है, तो आप किस मूल्य की तलाश करेंगे? उत्तर: तलाश करने के लिए कुछ भी नहीं है। सभी मूल्य अर्हता प्राप्त करते हैं।

मैं समझता हूं कि OPTION (RECOMPILE)एसक्यूएल सर्वर को यह देखने के लिए मजबूर करता है कि मापदंडों में क्या वास्तविक मूल्य हैं, और देखें कि क्या यह इसके साथ जुड़ सकता है।

लेकिन अब मैं आगे-संकलन का लाभ खो देता हूं।

सवाल

IMHO - SCAN केवल तभी होगा जब एक परम शून्य है।
यह ठीक है - SQL सर्वर को SCAN के लिए एक निष्पादन योजना बनाने दें।
लेकिन अगर SQL सर्वर देखता है कि मैं इस क्वेरी को मानों के साथ कई बार चलाता हूं: 1,1तो वह ANOTHER निष्पादन योजना क्यों नहीं बनाता है और उसके लिए SEEK का उपयोग करता है?

AFAIK - SQL सबसे हिट प्रश्नों के लिए निष्पादन योजना बनाता है ।

  • SQL SERVER के लिए निष्पादन योजना क्यों नहीं बचाती है:

    @productid int =1 , @priceid int = 1

(मैं इसे उन मूल्यों के साथ कई बार चलाता हूं)

  • क्या SQL को उस निष्पादन योजना (जो SEEK का उपयोग करता है) को भविष्य के आह्वान के लिए रखने के लिए मजबूर करना संभव है?

पूर्ण तालिका स्क्रिप्ट + डेटा बनाएँ


जवाबों:


10

हमारे चैट रूम चर्चा से कुछ मुख्य बिंदुओं को सारांशित करते हुए :


सामान्यतया, SQL सर्वर प्रत्येक कथन के लिए एक ही योजना को कैश करता है । यह योजना भविष्य के सभी संभावित पैरामीटर मानों के लिए मान्य होनी चाहिए ।

आपकी क्वेरी के लिए एक खोज योजना को कैश करना संभव नहीं है , क्योंकि यह योजना मान्य नहीं होगी, उदाहरण के लिए, @productid शून्य है।

कुछ भविष्य के रिलीज में, SQL सर्वर एकल योजना का समर्थन कर सकता है जो रनटाइम पैरामीटर मानों के आधार पर स्कैन और एक खोज के बीच चयन करता है, लेकिन यह कुछ ऐसा नहीं है जो आज हमारे पास है।

सामान्य समस्या वर्ग

आपकी क्वेरी एक पैटर्न का एक उदाहरण है जिसे विभिन्न रूप में "कैच ऑल" या "डायनामिक सर्च" क्वेरी के रूप में संदर्भित किया जाता है। विभिन्न समाधान हैं, प्रत्येक के अपने फायदे और नुकसान हैं। SQL सर्वर (2008+) के आधुनिक संस्करणों में, मुख्य विकल्प हैं:

  • IF ब्लॉक
  • OPTION (RECOMPILE)
  • गतिशील एसक्यूएल का उपयोग कर sp_executesql

विषय पर सबसे व्यापक काम संभवतः एर्लैंड सोमरसकोग द्वारा किया गया है, जो इस उत्तर के अंत में संदर्भों में शामिल है। इसमें शामिल जटिलताओं से दूर नहीं हो रहा है, इसलिए प्रत्येक मामले में ट्रेड-ऑफ को समझने के लिए प्रत्येक विकल्प की कोशिश करने में कुछ समय का निवेश करना आवश्यक है।

IF ब्लॉक

IFप्रश्न में विशिष्ट मामले के लिए एक ब्लॉक समाधान का वर्णन करने के लिए:

IF @productid IS NOT NULL AND @priceid IS NOT NULL
BEGIN
    SELECT 
        T.productID,
        T.priceID
    FROM dbo.Transactions AS T
    WHERE
        T.productID = @productid
        AND T.priceID = @priceid;
END;
ELSE IF @productid IS NOT NULL
BEGIN
    SELECT 
        T.productID,
        T.priceID
    FROM dbo.Transactions AS T
    WHERE
        T.productID = @productid;
END;
ELSE IF @priceid IS NOT NULL
BEGIN
    SELECT 
        T.productID,
        T.priceID
    FROM dbo.Transactions AS T
    WHERE
        T.priceID = @priceid;
END;
ELSE
BEGIN
    SELECT 
        T.productID,
        T.priceID
    FROM dbo.Transactions AS T;
END;

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

वहाँ पैरामीटर सूँघने के साथ एक संभावित समस्या है, जिसे OPTIMIZE FORप्रत्येक क्वेरी पर संकेत की आवश्यकता हो सकती है । इस प्रकार की सूक्ष्मताओं का पता लगाने के लिए कृपया संदर्भ अनुभाग देखें।

पुन: संयोजित

जैसा कि एक प्रश्न के ऊपर उल्लेख किया गया है, आप OPTION (RECOMPILE)प्रत्येक आह्वान पर एक नई योजना (तलाश या स्कैन) प्राप्त करने के लिए एक संकेत भी जोड़ सकते हैं । आपके मामले में कॉल की अपेक्षाकृत धीमी आवृत्ति को देखते हुए (औसतन हर दस सेकंड में एक बार उप-मिलीसेकंड संकलन समय के साथ) यह संभावना है कि यह विकल्प आपके लिए उपयुक्त होगा:

SELECT
    T.productID,
    T.priceID
FROM dbo.Transactions AS T
WHERE
    (T.productID = @productid OR @productid IS NULL)
    AND (T.priceID = @priceid OR @priceid IS NULL)
OPTION (RECOMPILE);

रचनात्मक तरीकों से उपरोक्त विकल्पों में से सुविधाओं को जोड़ना संभव है, जबकि डाउनडाइड्स को कम करते हुए प्रत्येक विधि का अधिकतम लाभ उठाना है। वास्तव में इस सामान को विस्तार से समझने का कोई शॉर्टकट नहीं है, फिर यथार्थवादी परीक्षण द्वारा समर्थित एक सूचित विकल्प बनाना।

आगे की पढाई

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