2011-03-25 16 views
6

कृपया Sql सर्वर में निम्नलिखित 2 बयान पर विचार करें:Sql सर्वर - बाहरी बनाम उप प्रश्नों लागू

यह एक नेस्टेड उप प्रश्नों उपयोग कर रहा है:

WITH cte AS 
(
    SELECT TOP 100 PERCENT * 
    FROM Segments 
    ORDER BY InvoiceDetailID, SegmentID 
) 
SELECT *, ReturnDate = 
       (SELECT TOP 1 cte.DepartureInfo 
        FROM cte 
        WHERE seg.InvoiceDetailID = cte.InvoiceDetailID 
         AND cte.SegmentID > seg.SegmentID), 
      DepartureCityCode = 
       (SELECT TOP 1 cte.DepartureCityCode 
        FROM cte 
        WHERE seg.InvoiceDetailID = cte.InvoiceDetailID 
         AND cte.SegmentID > seg.SegmentID) 
FROM Segments seg 

और यह एक बाहरी उपयोग करता लागू ऑपरेटर:

WITH cte AS 
(
    SELECT TOP 100 PERCENT * 
    FROM Segments 
    ORDER BY InvoiceDetailID, SegmentID 
) 
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode 
FROM Segments seg OUTER APPLY (
       SELECT TOP 1 cte.DepartureInfo, cte.DepartureCityCode 
       FROM cte 
       WHERE seg.InvoiceDetailID = cte.InvoiceDetailID 
         AND cte.SegmentID > seg.SegmentID 
      ) t 

इनमें से कौन सा 2 संभावित रूप से बेहतर प्रदर्शन करेगा क्योंकि दोनों सेगमेंट टेबल में संभावित रूप से लाखों पंक्तियां हो सकती हैं?

मेरा अंतर्ज्ञान बाहरी आवेदन बेहतर प्रदर्शन करेगा।

अधिक सवालों की एक जोड़ी:

  1. लगभग मैं इस बारे में काफी यकीन है, लेकिन अभी भी पुष्टि करते हैं कि पहले समाधान में चाहते थे, CTE प्रभावी रूप से दो बार क्रियान्वित किया जा सकता है (क्योंकि इसके दो बार जिक्र किया गया और CTE है एक मैक्रो की तरह विस्तारित इनलाइन)।
  2. आउटपुट ऑपरेटर ऑपरेटर में उपयोग किए जाने पर प्रत्येक पंक्ति के लिए एक बार सीटीई निष्पादित किया जाएगा? पहले कथन में नेस्टेड क्वेरी में इस्तेमाल होने पर भी प्रत्येक पंक्ति के लिए इसे निष्पादित किया जाएगा ??
+8

रन का निरीक्षण क्वेरी योजना बना रही है –

+1

'टॉप 100 प्रतिशत ... ऑर्डर बाय 'को रास्ते से अनुकूलित किया गया है और इसका कोई प्रभाव नहीं है। मैं सहमत हूं कि दूसरे को बेहतर प्रदर्शन करना चाहिए। प्रति समूह 'TOP 1' प्राप्त करने के लिए आप 'ROW_NUMBER' और' PARTITION BY' 'भी देख सकते हैं। –

उत्तर

4

सबसे पहले, सीटीई में Top 100 Percent से छुटकारा पाएं। आप यहां टॉप का उपयोग नहीं कर रहे हैं और यदि आप परिणाम सॉर्ट करना चाहते हैं, तो आपको पूरे कथन के अंत तक एक ऑर्डर जोड़ना चाहिए। दूसरा, प्रदर्शन के बारे में अपने प्रश्न को संबोधित करने के लिए, और अगर अनुमान लगाने के लिए मजबूर किया जाता है, तो मेरी शर्त केवल दूसरे रूप में होगी क्योंकि इसमें दो की बजाय एक एकल सबक्वायरी है। तीसरा, एक और रूप है जो आप की कोशिश कर सकते हो सकता है:

With RankedSegments As 
    (
    Select S1.SegmentId, ... 
     , Row_Number() Over(Partition By S1.SegmentId Order By S2.SegmentId) As Num 
    From Segments As S1 
     Left Join Segments As S2 
      On S2.InvoiceDetailId = S1.InvoiceDetailId 
       And S2.SegmentId > S1.SegmentID 
    ) 
Select ... 
From RankedSegments 
Where Num = 1 

एक और संभावना

With MinSegments As 
    (
    Select S1.SegmentId, Min(S2.SegmentId) As MinSegmentId 
    From Segments As S1 
     Join Segments As S2 
      On S2.InvoiceDetailId = S1.InvoiceDetailId 
       And S2.SegmentId > S1.SegmentID 
    Group By S1.SegmentId 
    ) 
Select ... 
From Segments As S1 
    Left Join (MinSegments As MS1 
     Join Segments As S2 
      On S2.SegmentId = MS1.MinSegmentId) 
     On MS1.SegmentId = S1.SegmentId 
+0

@ थॉमस: ऑर्डर बीई है क्योंकि बाहरी आवेदन/नेस्टेड प्रश्नों को क्रमबद्ध सही तालिका के विरुद्ध चलाने की आवश्यकता है, आपको लगता है कि मुझे शीर्ष 1 पंक्ति की आवश्यकता है और इसे सॉर्टेड तालिका से होना चाहिए, यही कारण है कि शीर्ष 100 प्रतिशत वहां से आदेश। हमम ... मुझे लगता है कि ROW_NUMBER भी एक अच्छा विकल्प होगा, मुझे आश्चर्य है कि मैंने इसे कैसे याद किया :(मैं इसे देखूंगा और वापस आऊंगा ... –

+0

@ थॉमस: दूसरी क्वेरी के सीटीई में 'ग्रुप बाय' गायब है। –

+0

@Andriy एम - दोह। फिक्स्ड। धन्यवाद। – Thomas

1

शायद मैं थॉमस 'क्वेरी का इस बदलाव का उपयोग करेगा:,

WITH cte AS 
(
SELECT *, Row_Number() Over(Partition By SegmentId Order By InvoiceDetailID, SegmentId) As Num 
FROM Segments) 
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode 
FROM Segments seg LEFT JOIN cte t ON seg.InvoiceDetailID = t.InvoiceDetailID AND t.SegmentID > seg.SegmentID AND t.Num = 1 
+0

यदि सेगमेंटआईडी पीके है, तो प्रत्येक पंक्ति के लिए संख्या 1 होगी। – Thomas

+0

हमम .. इसे इंगित करने के लिए धन्यवाद ... –

+0

@ थॉमस: हाँ सेगमेंट आईडी पीके है। मुझे लगता है कि आपके द्वारा पोस्ट किए गए एक सहित, इस मामले में भाग या उससे अधिक के आधार पर कोई भी समाधान संभव नहीं होगा। –