सामान्य तालिका अभिव्यक्ति (CTE) लाभ?


21

से MSDN :

एक व्युत्पन्न तालिका के विपरीत, एक सीटीई स्वयं-संदर्भित हो सकता है और एक ही क्वेरी में कई बार संदर्भित किया जा सकता है।

मैं सीटीई का काफी उपयोग कर रहा हूं, लेकिन मैंने उन्हें उपयोग करने के लाभों के बारे में गहराई से नहीं सोचा है।

यदि मैं एक ही क्वेरी में CTE को कई बार संदर्भित करता हूं:

  • क्या कोई प्रदर्शन लाभ है?
  • अगर मैं सेल्फ जॉइन कर रहा हूं, तो क्या SQL सर्वर लक्ष्य तालिकाओं को दो बार स्कैन करेगा?

2
यदि यह दो बार स्कैन करता है, तो आपको प्रॉसेसर को बताना चाहिए। IMHO, CTE की पुनरावृत्ति के लिए बहुत बढ़िया हैं।
दान एंड्रयूज

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

जवाबों:


25

एक नियम के रूप में, एक सीटीई कभी भी प्रदर्शन में सुधार नहीं करेगा

CTE अनिवार्य रूप से एक डिस्पोजेबल दृश्य है। कोई अतिरिक्त आँकड़े संग्रहीत नहीं हैं, कोई अनुक्रमणिका आदि नहीं हैं। यह एक उपश्रेणी के लिए एक आशुलिपि के रूप में कार्य करता है।

मेरी राय में वे ईएएसआईएलवाई से अधिक उपयोग किए जा सकते हैं (मुझे अपनी नौकरी में कोड का बहुत अधिक उपयोग होता है)। कुछ अच्छे उत्तर यहां दिए गए हैं, लेकिन यदि आपको एक से अधिक बार किसी चीज को संदर्भित करने की आवश्यकता है, या यह कुछ सौ हजार पंक्तियों से अधिक है, तो इसे #tempइसके बजाय एक तालिका में डालें और इसे अनुक्रमित करें।


3
इस बात से सहमत। पुनरावर्ती CTE को छोड़कर, तब वे केवल पठनीयता की सहायता करते हैं
gbn

क्या होगा यदि सीटीई केवल कुछ पंक्तियों को वापस करता है (ताकि उन्हें स्मृति में रखा जा सके) जो कि गणना करने के लिए महंगे हैं (बड़ी तालिका पर एकत्रीकरण) और उस परिणाम का एक से अधिक बार उपयोग किया जाता है? यह प्रदर्शन में सुधार करना चाहिए, है ना? (कम से कम यही मेरा अनुभव PostgreSQL और Oracle के साथ है जहाँ अस्थायी तालिका का उपयोग बहुत कम किया जाता है)
a_horse_with_no_name

2
@a_horse_with_no_name - यह सिर्फ एक उपश्रेणी बनाने के बराबर होगा। यदि परिणाम एक ही क्वेरी में एक से अधिक बार उपयोग किया जाता है, तो इसका पुन: उपयोग किया जाएगा और पुनर्गणना नहीं की जाएगी। यदि यह एक से अधिक क्वेरी में उपयोग किया जाता है, तो CTEएक बुरी पसंद है क्योंकि परिणाम पहली क्वेरी के बाद छोड़ दिए जाते हैं।
जेएनके

@ जेएनके: धन्यवाद। लगता है कि SQL सर्वर यहां अलग तरह से व्यवहार करता है।
a_horse_with_no_name

कुछ लोग कुछ परिस्थितियों में सीटीई के अधिक पठनीय पाते हैं FWIW stackoverflow.com/a/11170918/32453
rogerdpack

14

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

;WITH Conferences (Conference_id)
AS 
(select  m.Conference_id
FROM mydb.dbo.Conference m 
WHERE client_id = 10
    and Conference_id in 
            (select Conference_id from mydb.dbo.Expense 
            where amount <>0
            and amount is not null)
     )
--select * from Conferences
,MealEaters(NumberMealEaters, Conference_id, AttendeeType)
AS
(Select count(*) as NumberMealEaters, m.Conference_id,  AttendeeType 
from mydb.dbo.attendance ma 
join Conferences m on m.Conference_id = ma.Conference_id
where (ma.meals_consumed>0 or meals_consumed is null)and attended = 1
group by m.Conference_id)
--select * from MealEaters

,Expenses (Conference_id,expense_date, expenseDescription,  RecordIdentifier,amount)
AS
(select Conference_id,max(expense_date) as Expense_date, expenseDescription,  RecordIdentifier,sum(amount) as amount
    FROM
        (SELECT Conference_id,expense_date,  amount, RecordIdentifier
        FROM mydb.dbo.Expense
        WHERE  amount <> 0 
            and Conference_id IN 
            (SELECT  Conference_id
            FROM mydb.dbo.Conferences ) 
        group by Conference_id, RecordIdentifier) a
)
--select * from Expenses
Select m.Conference_id,me.NumberMealEaters, me.AttendeeType, e.expense_date,         e.RecordIdentifier,amount
from Conferences m
join mealeaters me on m.Conference_id = me.Conference_id
join expenses e on e.Conference_id = m.Conference_id

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


1
सिर्फ रिपोर्टिंग के लिए सवाल? हर दिन मैं जिन प्रणालियों पर काम करता हूं, उनमें लेनदेन संबंधी प्रश्न होते हैं जो कि जटिल होते हैं। अजीब तरह से हमारे रिपोर्टिंग प्रश्न अक्सर हमारे कुछ सरल होते हैं। (पाठ्यक्रम के तुच्छ ज्वाइनलेस सीआरयूडी प्रश्नों को छोड़कर)।
केविन कैथार्ट

मैंने इसका उपयोग उदाहरण के रूप में किया क्योंकि वे आमतौर पर यहाँ सबसे जटिल हैं
HLGEM

+1 कभी-कभी संभावित रूप से बेहतर प्रदर्शन करने वाले के लिए एक अधिक तार्किक (मानव पठनीय) क्वेरी बेहतर होती है।
onedaywhen

हाँ। यह देखते हुए कि एक सीटीई आमतौर पर एक ही परिणामी योजना का उत्पादन करेगा, मुझे कोई कारण नहीं है कि हम भयावह रूप से नेस्टेड, मल्टी-सबक्वेरी मठों को बनाने का कोई कारण नहीं देखते हैं - जब हम प्रत्येक घटक को नेत्रहीन रूप से क्रम में रख सकते हैं, जिसकी उन्हें आवश्यकता है। मैं XML फ़ाइलों को आयात करता हूं और डेटा को सही रूप में प्राप्त करने के लिए विभिन्न कलाबाजी करता हूं, जो सीटीई के बिना लिखने / पढ़ने के लिए असहनीय होगा। (मेरे कुछ पुराने कोड में शायद सभी दौर में भयानक उपश्रेणियाँ हैं!)
अंडरस्कोर_ड

0

हमेशा की तरह यह निर्भर करता है लेकिन ऐसे मामले हैं जहां प्रदर्शन में बहुत सुधार होता है। मैं इसे INSERT INTO SELECT स्टेटमेंट्स के साथ देखता हूं जहां आप चयन के लिए CTE का उपयोग करते हैं और फिर INSERT INTO में उसका उपयोग करते हैं। यह आरसीएसआई को डेटाबेस के लिए सेट किए जाने के साथ करना पड़ सकता है लेकिन उन समय के लिए जब बहुत कम का चयन किया जाता है तो यह काफी मदद कर सकता है।

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