यदि किसी प्रश्न में CTE को परिभाषित किया जाता है और उसका उपयोग कभी नहीं किया जाता है, तो क्या यह ध्वनि करता है?


32

क्या क्वेरी में अप्रयुक्त सीटीई प्रदर्शन को प्रभावित करते हैं और / या उत्पन्न क्वेरी योजना में परिवर्तन करते हैं?

जवाबों:


21

ऐसा नहीं लगता कि वे ऐसा करते हैं, लेकिन यह वास्तव में केवल नेस्टेड सीटीई पर लागू होता है।

दो अस्थायी तालिकाएँ बनाएँ:

CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );

CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );

प्रश्न 1:

WITH your_mom AS (
    SELECT TOP 1 *
    FROM #t1 AS t 
),
also_your_mom AS (
    SELECT TOP 1 *
    FROM #t2 AS t
)
SELECT *
FROM your_mom;

क्वेरी 2:

WITH your_mom AS (
    SELECT TOP 1 *
    FROM #t1 AS t 
),
also_your_mom AS (
    SELECT TOP 1 *
    FROM #t2 AS t
)
SELECT *
FROM also_your_mom;

क्वेरी योजना:

पागल

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


28

+1 से एरिक, लेकिन दो चीजों को जोड़ना चाहते थे (जो एक टिप्पणी में अच्छी तरह से काम नहीं करते थे):

  1. आपको यह देखने के लिए निष्पादन योजनाओं को देखने की भी आवश्यकता नहीं है कि उनका उपयोग न किए जाने पर अनदेखा किया जाता है। निम्नलिखित को "0 से विभाजित करें" त्रुटि का उत्पादन करना चाहिए, लेकिन इसके cte2बिल्कुल भी चयनित नहीं होने के कारण :

    ;WITH cte1 AS
    (
      SELECT 1 AS [Bob]
    ),
    cte2 AS (
      SELECT 1 / 0 AS [Err]
      FROM cte1
    )
    SELECT *
    FROM   cte1;
  2. CTE को नजरअंदाज किया जा सकता है, भले ही वे केवल CTE हों, और भले ही वे किससे चुने गए हों, यदि तार्किक रूप से सभी पंक्तियों को वैसे भी बाहर रखा जाएगा। निम्नलिखित एक ऐसा मामला है जहां क्वेरी ऑप्टिमाइज़र समय से पहले जानता है कि सीटीई से कोई पंक्तियाँ नहीं लौटाई जा सकती हैं, इसलिए यह इसे निष्पादित करने के लिए परेशान नहीं करता है:

    ;WITH cte AS
    (
      SELECT 1 / 0 AS [Bob]
    )
    SELECT TOP (1) [object_id]
    FROM   sys.objects
    UNION ALL
    SELECT cte.[Bob]
    FROM   cte
    WHERE  1 = 0;

प्रदर्शन के संबंध में, अप्रयुक्त सीटीई को पार्स और संकलित किया जाता है (या नीचे के मामले में कम से कम संकलित किया जाता है), इसलिए इसे 100% अनदेखा नहीं किया जाता है, लेकिन लागत को नगण्य होना चाहिए और इसके बारे में चिंतित होने के लायक नहीं है।

जब केवल पार्सिंग होता है, तो कोई त्रुटि नहीं होती है:

SET PARSEONLY ON;

;WITH cte1 AS
(
  SELECT obj.[NotHere]
  FROM   sys.objects obj
)
SELECT TOP (1) so.[name]
FROM   sys.objects so

GO
SET PARSEONLY OFF;
GO

जब सब कुछ करने के लिए निष्पादन की कमी है, तो एक समस्या है:

GO
SET NOEXEC ON;
GO

;WITH cte1 AS
(
  SELECT obj.[NotHere]
  FROM   sys.objects obj
)
SELECT TOP (1) so.[name]
FROM   sys.objects so

GO
SET NOEXEC OFF;
GO
/*
Msg 207, Level 16, State 1, Line XXXXX
Invalid column name 'NotHere'.
*/

काश मैं सही के रूप में एक से अधिक उत्तर को चिह्नित कर सकता, लेकिन एरिक ने आपको पिस्तौल ड्रा में हरा दिया। :) लेकिन आपका जवाब बहुत जानकारीपूर्ण और महान है, धन्यवाद!
जेडी

क्या होगा यदि CTE एक दृश्य में हो और दृश्य 3 बार से अधिक नस्ट हो? क्या ऐसा कोई बिंदु नहीं है जहाँ अनुकूलक आशावादी होकर सब चलाता हो?
ज़िकैटो

@Zikato मुझे कोई पता नहीं है, लेकिन यह एक बड़ा सवाल है। आप पहले दो उदाहरणों में दिखाए गए शून्य चाल से विभाजन का उपयोग करके एक दृश्य बनाने के बिना बहुत अधिक प्रयास के बिना एक परीक्षण स्थापित करने में सक्षम होना चाहिए। कृपया मुझे परिणाम बताएं क्योंकि मैं इस परिदृश्य के बारे में बहुत उत्सुक हूं :-)।
सोलोमन रटज़की

@SolomonRutzky निष्पक्ष होने के लिए, मैंने इसका परीक्षण किया, लेकिन यह निर्णायक नहीं था। मैंने आपके cte उदाहरण से एक दृश्य बनाया है और इसे 5 बार नेस्ट किया है, लेकिन चूंकि यह सभी निरंतर स्कैन है और वास्तव में जटिल नहीं है, इसलिए अनुकूलक ने इसे अच्छी तरह से संभाला है। मैं भविष्य में इसे और अच्छी तरह से परखना चाहता हूं और इसे और अधिक जटिल तर्क के पीछे छिपाता हूं। मैं आपको बता दूँगा।
जीकाटो

@Zikato दिलचस्प। निश्चित नहीं है कि क्या "जटिल" माना जाएगा, लेकिन हां, मेरा उदाहरण बहुत सरल है। जब आप "इसे 5 बार नेस्टेड" कहते हैं, तो क्या आपका मतलब अन्य विचारों / प्रोक्स में है जो एक दूसरे को कहते हैं और यह 5 गहरा था, या उपश्रेणियों / सीटीई में? मुझे लगता है कि संभावना है कि पर्याप्त स्तर के घोंसले के शिकार इसे छोड़ सकते हैं, लेकिन इसकी वजह से इसे संदर्भित नहीं किया जा रहा है, बल्कि इसके बजाय एक उच्च घोंसला स्तर का उपयोग नहीं करने के कारण और यह निचले स्तरों के लिए ग्रहण किया जा रहा है। मैंने देखा है कि NEWID()यूडीएफ में उपयोग करने के लिए एक दृश्य में डालने की ट्रिक इसे ऑप्टिमाइज़र के कैशिंग के कारण एक से अधिक कॉल से एक ही मान वापस कर सकती है।
सोलोमन रटज़की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.