SARGable विधेयकों को CTE या व्युत्पन्न तालिका में कब धकेला जा सकता है?


15

रेत से भरा बोरा

पर शीर्ष गुणवत्ता ब्लॉग Posts® काम करते हुए, मैं कुछ अनुकूलक व्यवहार मैं वास्तव में पाया में आए क्रुद्ध दिलचस्प। मेरे पास तुरंत कोई स्पष्टीकरण नहीं है, कम से कम ऐसा नहीं है जिससे मैं खुश हूं, इसलिए मैं इसे यहां डाल रहा हूं, अगर कोई स्मार्ट शो करता है।

यदि आप साथ चलना चाहते हैं, तो आप यहां स्टैक ओवरफ्लो डेटा डंप के 2013 संस्करण को पकड़ सकते हैं । मैं टिप्पणियाँ तालिका का उपयोग कर रहा हूं, उस पर एक अतिरिक्त सूचकांक के साथ।

CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC );

क्वेरी एक

जब मैं तालिका की तरह क्वेरी करता हूं, तो मुझे एक अजीब क्वेरी योजना मिलती है ।

WITH x
    AS
     (
         SELECT   TOP 101
                  c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
         ORDER BY c.Score DESC
     )
SELECT *
FROM   x
WHERE  x.Score >= 500;

पागल

SARGable स्कोर पर समर्पित CTE के अंदर धकेल नहीं है। यह योजना में बहुत बाद में एक फिल्टर ऑपरेटर में है।

पागल

जो मुझे अजीब लगता है, चूंकि ORDER BYफिल्टर के समान कॉलम पर है।

क्वेरी दो

यदि मैं क्वेरी को बदलता हूं, तो यह पुश हो जाता है।

WITH x
    AS
     (
         SELECT   c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
     )
SELECT TOP 101 *
FROM   x
WHERE  x.Score >= 500
ORDER BY x.Score DESC;

क्वेरी योजना बदलता है , भी, और डिस्क के लिए कोई रिसाव के साथ बहुत तेजी से चलता है। वे दोनों एक ही परिणाम उत्पन्न करते हैं, गैर-अनुक्रमित सूचकांक स्कैन में विधेय के साथ।

पागल

पागल

क्वेरी तीन

यह क्वेरी को इस तरह लिखने के बराबर है:

SELECT   TOP 101
         c.UserId, c.Text, c.Score
FROM     dbo.Comments AS c
WHERE c.Score >= 500
ORDER BY c.Score DESC;

चतुर्थ भाव

व्युत्पन्न तालिका का उपयोग करने पर प्रारंभिक सीटीई क्वेरी के समान "खराब" क्वेरी योजना मिलती है

SELECT *
FROM   (   SELECT   TOP 101
                    c.UserId, c.Text, c.Score
           FROM     dbo.Comments AS c
           ORDER BY c.Score DESC ) AS x
WHERE x.Score >= 500;

चीजें तब भी अजीब हो जाती हैं जब ...

मैं डेटा को आरोही करने के लिए क्वेरी को बदलता हूं, और फ़िल्टर को <=

इस सवाल को लंबे समय तक बनाए रखने के लिए, मैं सब कुछ एक साथ रखने जा रहा हूं।

प्रश्नों

--Derived table
SELECT *
FROM   (   SELECT   TOP 101
                    c.UserId, c.Text, c.Score
           FROM     dbo.Comments AS c
           ORDER BY c.Score ASC ) AS x
WHERE x.Score <= 500;


--TOP inside CTE
WITH x
    AS
     (
         SELECT   TOP 101
                  c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
         ORDER BY c.Score ASC
     )
SELECT *
FROM   x
WHERE  x.Score <= 500;


--Written normally
SELECT   TOP 101
         c.UserId, c.Text, c.Score
FROM     dbo.Comments AS c
WHERE c.Score <= 500
ORDER BY c.Score ASC;

--TOP outside CTE
WITH x
    AS
     (
         SELECT   c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
     )
SELECT TOP 101 *
FROM   x
WHERE  x.Score <= 500
ORDER BY x.Score ASC;

योजनाओं

योजना लिंक

पागल

ध्यान दें कि इन प्रश्नों में से कोई भी गैर-अनुक्रमित सूचकांक का लाभ नहीं उठाता है - केवल एक चीज जो यहां बदलती है वह फ़िल्टर ऑपरेटर की स्थिति है। किसी भी स्थिति में सूचकांक पहुंच के लिए प्रेरित विधेय नहीं है।

एक प्रश्न दिखाई देता है!

क्या कोई कारण है कि SARGable विधेय को कुछ परिदृश्यों में धकेला जा सकता है और दूसरों में नहीं? अवरोही क्रम में हल किए गए प्रश्नों के अंतर दिलचस्प हैं, लेकिन उन और उन लोगों के बीच के अंतर जो विचित्र आरोही हैं।

रुचि रखने वाले किसी व्यक्ति के लिए, यहां केवल एक इंडेक्स के साथ योजनाएं हैं Score:

जवाबों:


11

यहाँ खेलने में कुछ मुद्दे हैं।

धक्का लगाना अतीत की भविष्यवाणी करता है TOP

आशावादी वर्तमान में एक विधेय को आगे नहीं बढ़ा सकता है TOP, यहां तक ​​कि सीमित मामलों में भी जहां ऐसा करना सुरक्षित होगा *। यह सीमा प्रश्न में उन सभी प्रश्नों के व्यवहार के लिए है जहाँ विधेय की तुलना में अधिक गुंजाइश है TOP

चारों ओर का काम मैन्युअल रूप से फिर से लिखना है। मौलिक मुद्दा एक विंडो फ़ंक्शन के पिछले विधेय को आगे बढ़ाने के मामले के समान है , सिवाय इसके कि कोई विशेष नियम जैसा नहीं है SelOnSeqPrj

मेरी निजी राय है कि एक अन्वेषण नियम की तरह SelOnTopही लागू नहीं किया जाता है क्योंकि लोगों ने जानबूझकर TOPएक प्रकार का 'अनुकूलन बाड़' प्रदान करने के प्रयास के साथ प्रश्न लिखे हैं ।

* आम तौर पर इसका मतलब यह है कि विधेय को ORDER BYसंबंधित खंड में प्रकट होना चाहिए TOP, और किसी भी असमानता की दिशा को छंटाई की दिशा से सहमत होना चाहिए। SQL सर्वर में NULLs के सॉर्टिंग व्यवहार के लिए परिवर्तन को भी ध्यान में रखना होगा। कुल मिलाकर, सीमाओं का मतलब शायद यह है कि अतिरिक्त अन्वेषण प्रयासों को सही ठहराने के लिए यह परिवर्तन आम तौर पर पर्याप्त उपयोगी नहीं होगा।

लागत के मुद्दे

प्रश्न में शेष निष्पादन योजनाओं को Scoreकॉलम में मूल्यों के वितरण (कई और पंक्तियों <= 500 से> = 500) के कारण लागत आधारित विकल्पों के रूप में समझाया जा सकता है , और इसके द्वारा शुरू किए गए पंक्ति लक्ष्य का प्रभाव TOP

उदाहरण के लिए, क्वेरी:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score <= 500
ORDER BY
    c.Score ASC;

... एक फिल्टर में एक स्पष्ट रूप से अप्रकाशित विधेय के साथ एक योजना तैयार करता है:

पंक्ति लक्ष्य के कारण देर से फ़िल्टर

ध्यान दें कि क्रमबद्ध 101 पंक्तियों का उत्पादन करने का अनुमान है। यह शीर्ष द्वारा जोड़े गए पंक्ति लक्ष्य का प्रभाव है। यह सॉर्ट और फ़िल्टर की अनुमानित लागत को प्रभावित करता है जिससे यह प्रतीत होता है कि यह सबसे सस्ता विकल्प है। इस योजना की अनुमानित लागत 2401.39 इकाई है।

यदि हम एक पंक्ति संकेत के साथ पंक्ति लक्ष्यों को अक्षम करते हैं:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score <= 500
ORDER BY
    c.Score ASC
OPTION (USE HINT ('DISABLE_OPTIMIZER_ROWGOAL'));

... क्रियान्वित योजना है:

पंक्ति लक्ष्य के बिना योजना

विधेय को स्कैन में अवशिष्ट गैर-सारगर्भित विधेय के रूप में धकेल दिया गया है, और संपूर्ण योजना की लागत 2402.32 इकाई है।

ध्यान दें कि <= 500विधेय किसी भी पंक्तियों को फ़िल्टर करने की अपेक्षा नहीं करता है। यदि आपने एक छोटी संख्या को चुना है, जैसे <= 50, आशावादी ने पंक्ति लक्ष्य प्रभाव की परवाह किए बिना पुश-पेडिकट योजना को प्राथमिकता दी होगी।

क्वेरी के साथ Score DESCऔर एक Score >= 500विधेय के लिए:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score >= 500
ORDER BY
    c.Score DESC;

अब विधेय बहुत चयनात्मक होने की उम्मीद है, इसलिए आशावादी विधेय को धकेलने के लिए चुनता है और लुकअप के साथ गैर-अनुक्रमित सूचकांक का उपयोग करता है:

चयनात्मक विधेय

फिर से, आशावादी ने कई विकल्पों पर विचार किया और इसे हमेशा की तरह सबसे सस्ता विकल्प चुना।

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