क्या सीटीई, सब-क्वेरी, अस्थायी तालिका या टेबल चर के बीच एक प्रदर्शन अंतर है?


222

इस उत्कृष्ट एसओ प्रश्न में , के बीच अंतर CTEऔर sub-queriesचर्चा की गई थी।

मैं विशेष रूप से पूछना चाहूंगा:

निम्नलिखित में से प्रत्येक किस परिस्थिति में अधिक कुशल / तेज है?

  • CTE
  • उप-क्वेरी
  • अस्थायी तालिका
  • तालिका चर

परंपरागत रूप से, मैंने बहुत से temp tablesविकासशील का उपयोग किया है stored procedures- क्योंकि वे बहुत सारे इंटरव्यू किए गए उप-प्रश्नों की तुलना में अधिक पठनीय लगते हैं।

Non-recursive CTEडेटा के सेटों को बहुत अच्छी तरह से समझाया जाता है, और बहुत ही पठनीय होते हैं, लेकिन क्या ऐसी विशिष्ट परिस्थितियाँ हैं जहाँ कोई कह सकता है कि वे हमेशा बेहतर प्रदर्शन करेंगे? या यह सबसे कुशल समाधान खोजने के लिए हमेशा विभिन्न विकल्पों के साथ चारों ओर बेतरतीब होने का मामला है?


संपादित करें

मुझे हाल ही में बताया गया है कि दक्षता के मामले में, अस्थायी टेबल एक अच्छी पहली पसंद है क्योंकि उनके पास संबंधित हिस्टोग्राम यानी आँकड़े हैं।


4
सामान्य उत्तर: यह निर्भर करता है। और यह कुछ कारकों पर निर्भर करता है, किसी भी सामान्य कथन में कुछ स्थितियों में - गलत है। मूल रूप से: आपको परीक्षण करने और मापने की आवश्यकता है - देखें कि आपके लिए कौन सा सबसे अच्छा काम करता है!
marc_s

@marc_s - ठीक; शायद व्यक्तिपरक होने के लिए इस सवाल को बंद कर दिया जाना चाहिए? ध्यान रहे कि एसओ पर बहुत सारे एसक्यूएल प्रश्नों को व्यक्तिपरक के रूप में आंका जा सकता है।
Whytheq

1
यह बहुत व्यापक होने के कारण बंद हो सकता है - और मैं आपसे सहमत हूं - SQL में बहुत सारी चीजें और विषय वास्तव में इसका जवाब मिलेगा । कभी-कभी कोई निर्णय लेने के लिए दो या तीन मानदंडों को सूचीबद्ध कर सकता है, लेकिन यहां आपके प्रश्न के साथ, ध्वनि सलाह देना असंभव के बगल में है - यह बहुत कुछ निर्भर करता है - आपकी तालिका संरचनाएं, उन तालिकाओं में डेटा, आपके द्वारा उपयोग किए जा रहे प्रश्न, आपकी अनुक्रमण रणनीति और भी बहुत कुछ ....
marc_s

@marc_s कोशिश करने और रखने के लिए अच्छा होगा - ओपी के संभावित संपादन पर कोई सलाह इसे और अधिक विशिष्ट और संकीर्ण बनाने की कोशिश करना?
Whytheq

कृपया ध्यान दें कि यह प्रश्न SQL सर्वर के लिए विशिष्ट है। पोस्टग्रेज जैसे अन्य DB के लिए, एक CTE अक्सर समान उपश्रेणियों की तुलना में बहुत धीमा होता है (देखें http://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/ )
Jay

जवाबों:


243

एसक्यूएल एक घोषित भाषा है, प्रक्रियात्मक भाषा नहीं है। यही है, आप अपने इच्छित परिणामों का वर्णन करने के लिए SQL कथन का निर्माण करते हैं। आप एसक्यूएल इंजन को यह नहीं बता रहे हैं कि काम कैसे करना है।

एक सामान्य नियम के रूप में, एसक्यूएल इंजन और एसक्यूएल ऑप्टिमाइज़र को सर्वश्रेष्ठ क्वेरी प्लान खोजने देना एक अच्छा विचार है। कई व्यक्ति-वर्ष के प्रयास हैं जो एक एसक्यूएल इंजन को विकसित करने में जाते हैं, इसलिए इंजीनियरों को वही करना चाहिए जो वे जानते हैं कि उन्हें कैसे करना है।

बेशक, ऐसी परिस्थितियां हैं जहां क्वेरी योजना इष्टतम नहीं है। फिर आप क्वेरी संकेत का उपयोग करना चाहते हैं, क्वेरी को पुन: व्यवस्थित करें, आंकड़े अपडेट करें, अस्थायी तालिकाओं का उपयोग करें, अनुक्रमित जोड़ें, और इसी तरह बेहतर प्रदर्शन प्राप्त करें।

अपने प्रश्न के लिए के रूप में। CTE और सबक्वेरी का प्रदर्शन, सिद्धांत में होना चाहिए, क्योंकि दोनों ही क्वेरी ऑप्टिमाइज़र को समान जानकारी प्रदान करते हैं। एक अंतर यह है कि एक से अधिक सीटीई का उपयोग एक बार में आसानी से पहचाना और गणना की जा सकती है। परिणाम कई बार संग्रहीत और पढ़े जा सकते हैं। दुर्भाग्य से, SQL सर्वर इस मूल अनुकूलन विधि का लाभ नहीं उठाता है (आप इसे सामान्य उपशमन उन्मूलन कह सकते हैं)।

अस्थायी तालिकाएँ एक अलग मामला है, क्योंकि आप क्वेरी को कैसे चलाया जाना चाहिए, इस बारे में अधिक मार्गदर्शन प्रदान कर रहे हैं। एक बड़ा अंतर यह है कि ऑप्टिमाइज़र अपनी क्वेरी योजना को स्थापित करने के लिए अस्थायी तालिका के आँकड़ों का उपयोग कर सकता है। इससे प्रदर्शन लाभ हो सकता है। इसके अलावा, यदि आपके पास एक जटिल सीटीई (उपश्रेणी) है जो एक से अधिक बार उपयोग किया जाता है, तो इसे एक अस्थायी तालिका में संग्रहीत करना अक्सर एक प्रदर्शन को बढ़ावा देगा। क्वेरी को केवल एक बार निष्पादित किया जाता है।

आपके प्रश्न का उत्तर यह है कि आपको अपने प्रदर्शन की अपेक्षा के लिए खेलने की आवश्यकता है, विशेष रूप से जटिल प्रश्नों के लिए जो नियमित रूप से चलते हैं। एक आदर्श दुनिया में, क्वेरी ऑप्टिमाइज़र को सही निष्पादन पथ मिलेगा। हालांकि यह अक्सर होता है, आप बेहतर प्रदर्शन पाने का एक तरीका खोजने में सक्षम हो सकते हैं।


11
इस क्षेत्र में संभावित भविष्य के सुधारों पर कुछ Microsoft शोध " यहाँ से उपलब्ध
मार्टिन स्मिथ

3
उस पेपर को 2007 में प्रस्तुत किया गया था, यह देखते हुए कि क्या उन्होंने इसे SQL Server 2012 में शामिल किया है?
गॉर्डन लिनोफ

3
एक महान जवाब! बस जोर देने के लिए: एसक्यूएल एक घोषणात्मक भाषा है, और हम नियंत्रण नहीं करते हैं कि डेटा कैसे खींचा जाता है। इसलिए, प्रदर्शन / गति क्वेरी से क्वेरी में भिन्न होती है।
सिमका खाबिंस्की

2
@ आरजीएस। । । अस्थायी तालिकाओं पर अनुक्रमणिका निश्चित रूप से उन प्रश्नों को सुधारती है जो उन सूचियों का लाभ उठा सकते हैं - जैसे कि एक स्थायी तालिका पर अनुक्रमणिका के साथ। लेकिन, यदि आप एक अस्थायी तालिका के रूप में एक उपश्रेणी को उत्प्रेरित करते हैं, तो आप मूल तालिकाओं पर अनुक्रमित का लाभ खो सकते हैं।
गॉर्डन लिनोफ़

2
@ आरजीएस। । जब एक डेटाबेस इंजन एक जटिल क्वेरी को निष्पादित करने के दौरान एक सबक्वेरी / CTE को मटेरियल करता है, तो यह भौतिककरण पर अनुक्रमित नहीं करता है। आप अस्थायी टेबल का उपयोग करके मैन्युअल रूप से कर सकते हैं।
गॉर्डन लिनोफ

77

कोई नियम नहीं है। मुझे CTE अधिक पठनीय लगते हैं, और उनका उपयोग तब तक करते हैं जब तक कि वे कुछ प्रदर्शन समस्या का प्रदर्शन नहीं करते हैं, जिस स्थिति में मैं वास्तविक समस्या की जांच करता हूं, बजाय यह अनुमान लगाए कि सीटीई समस्या है और एक अलग दृष्टिकोण का उपयोग करके इसे फिर से लिखने का प्रयास करें। क्वेरी के साथ मेरे इरादे को स्पष्ट रूप से बताने के तरीके के मुकाबले आम तौर पर इस मुद्दे पर अधिक है।

निश्चित रूप से ऐसे मामले हैं जब आप सीटीई को हटा सकते हैं या उपश्रेणियों को हटा सकते हैं और उन्हें एक # टेबल टेबल के साथ बदल सकते हैं और अवधि को कम कर सकते हैं। यह विभिन्न चीजों के कारण हो सकता है, जैसे कि बासी आँकड़े, सटीक आँकड़े प्राप्त करने की अक्षमता (जैसे कि एक टेबल-वैल्यू फ़ंक्शन में शामिल होना), समानता या यहां तक ​​कि क्वेरी की जटिलता के कारण एक इष्टतम योजना बनाने में असमर्थता ( जो मामले में इसे तोड़ने से अनुकूलक को लड़ने का मौका मिल सकता है)। लेकिन ऐसे भी मामले हैं जिनमें #temp तालिका बनाने के साथ शामिल I / O अन्य प्रदर्शन पहलुओं को पछाड़ सकता है जो CTE कम आकर्षक का उपयोग करके एक विशेष योजना आकार बना सकते हैं।

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

इसलिए मैं आपको इस तरह से क्वेरी लिखने का सुझाव दूंगा जो आपके लिए सबसे स्वाभाविक लगता है, और केवल तब ही विचलित हो जाता है जब आपको एक वास्तविक प्रदर्शन समस्या का पता चलता है जो ऑप्टिमाइज़र के पास है। व्यक्तिगत रूप से मैं उन्हें CTE रैंक देता हूं, फिर सबट्री, # टैम्प टेबल के साथ एक अंतिम उपाय है।


4
+1 काफी व्यक्तिपरक प्रश्न है; मुझे आशा है कि यह बहुत अस्पष्ट होने के कारण बंद नहीं होगा क्योंकि उत्तर इस प्रकार जानकारीपूर्ण हैं। मुझे एहसास है कि आप इसे पसंद नहीं करते हैं जब प्रश्न बदलते हैं लेकिन क्या आपके पास ओपी में सवाल को कम करने के लिए कोई सुझाव है?
Whytheq

2
मुझे लगता है कि यह सवाल ठीक है, आप देखेंगे कि अभी तक एक भी वोट-पास नहीं हुआ है, लेकिन यदि उत्तर बेतहाशा घूमने लगे तो शायद यह बंद हो जाएगा। जैसा कि मैंने अपने उत्तर में सुझाव दिया है, यदि आपके पास एक विशेष मामला है जहां आप एक सीटीई और एक उपश्रेणी के बीच एक बड़ा अंतर देखते हैं, तो वास्तविक प्रश्नों और निष्पादन योजनाओं के साथ एक नया प्रश्न शुरू करें (और यह dba.se पर बेहतर फिट हो सकता है ) । बस महसूस करें कि उस क्वेरी के साथ मदद करने का उत्तर एक ही परिदृश्य के साथ एक अलग क्वेरी के लिए एक ही उत्तर नहीं हो सकता है।
हारून बर्ट्रेंड

आपके प्रश्न के ठीक नीचे लिंक हैं link / edit / close / flag- यदि प्रश्न को बंद करने के लिए कोई वोट दिया गया है, तो आप देखेंगे close (n)कि nआपके प्रश्न को बंद करने के लिए मतदान करने वाले उपयोगकर्ताओं की संख्या का प्रतिनिधित्व करता है। यदि आप लिंक पर क्लिक करते हैं, तो आप उन कारणों को देखेंगे जो उन उपयोगकर्ताओं ने चुने हैं।
हारून बर्ट्रेंड

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

1
उपरोक्त लिंक: sqlskills.com/blogs/bobb/…
ADJenks

19

# टैम्प को matalized किया गया है और CTE नहीं है।

CTE सिर्फ वाक्यविन्यास है इसलिए सिद्धांत रूप में यह सिर्फ एक उपश्रेणी है। इसे अंजाम दिया जाता है। # टैम्प को भौतिक किया जाता है। तो एक महंगी CTE जो कि कई बार निष्पादित हो जाती है, एक #temp में बेहतर हो सकती है। दूसरी तरफ यदि यह एक आसान मूल्यांकन है जिसे निष्पादित नहीं किया गया है, लेकिन कुछ बार तो #temp के ओवरहेड के लायक नहीं है।

SO पर कुछ लोग हैं जो टेबल वैरिएबल को पसंद नहीं करते हैं लेकिन मैं उन्हें पसंद करता हूं क्योंकि वे #temp की तुलना में भौतिक और तेज़ हैं। ऐसे समय होते हैं जब क्वेरी ऑप्टिमाइज़र तालिका चर की तुलना में #temp के साथ बेहतर करता है।

#Temp या टेबल वैरिएबल पर PK बनाने की क्षमता क्वेरी ऑप्टिमाइज़र को CTE से अधिक जानकारी देती है (जैसा कि आप CTE पर PK घोषित नहीं कर सकते हैं)।


"TVP" का संक्षिप्त नाम क्या है ... #temp के समान?
Whytheq

टीवीपी एक सामान्य शब्द बनता जा रहा है, क्योंकि यह प्रभावशाली (कुछ करने के लिए) लगता है। संक्षेप में, एक टीवीपी एक तालिका है जिसे एक पैरामीटर के रूप में पारित किया जाता है। जिन लोगों ने टेबल चर का उपयोग किया है, वे उनके साथ घर पर सही होंगे।
वंडरवर्कर

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

12

मुझे लगता है कि सिर्फ 2 चीजें यह हमेशा एक # अस्थायी तालिका का उपयोग करने के लिए बेहतर है, बल्कि एक CTE हैं:

  1. आप एक CTE पर एक प्राथमिक कुंजी नहीं रख सकते हैं, इसलिए CTE द्वारा एक्सेस किए जा रहे डेटा को CTE की तालिकाओं में प्रत्येक एक अनुक्रमणिका को पार करना होगा, बजाय इसके बाद केवल अस्थायी तालिका पर PK या अनुक्रमणिका को एक्सेस करना होगा।

  2. क्योंकि आप एक CTE में बाधा, अनुक्रमित और प्राथमिक कुंजी नहीं जोड़ सकते हैं, वे खराब और खराब डेटा में कीड़े के लिए अधिक प्रवण हैं।


-सोने कल

यहां एक उदाहरण दिया गया है जहां #table बाधाएं खराब डेटा को रोक सकती हैं जो कि CTE के मामले में नहीं है

DECLARE @BadData TABLE ( 
                       ThisID int
                     , ThatID int );
INSERT INTO @BadData
       ( ThisID
       , ThatID
       ) 
VALUES
       ( 1, 1 ),
       ( 1, 2 ),
       ( 2, 2 ),
       ( 1, 1 );

IF OBJECT_ID('tempdb..#This') IS NOT NULL
    DROP TABLE #This;
CREATE TABLE #This ( 
             ThisID int NOT NULL
           , ThatID int NOT NULL
                        UNIQUE(ThisID, ThatID) );
INSERT INTO #This
SELECT * FROM @BadData;
WITH This_CTE
     AS (SELECT *
           FROM @BadData)
     SELECT *
       FROM This_CTE;

3
ALWAYSथोड़ा बहुत दूर है, लेकिन उत्तर के लिए धन्यवाद। पठनीयता के संदर्भ में सीटीई का उपयोग एक अच्छी बात हो सकती है।
Whytheq

3
मैं आपके दूसरे बिंदु को बिल्कुल नहीं समझता। जिस तरह से मैं इसे देखता हूं, सीटीई को परिभाषित करने वाली क्वेरी उस गतिरोध के अनुरूप होती है जिसे आप अस्थायी तालिका में डालते हैं, यह देखते हुए कि पूर्व में मनमाने ढंग से जटिल विधेय शामिल हो सकते हैं जबकि उत्तरार्द्ध कहीं अधिक सीमित है (उदाहरण के CHECKलिए कई पंक्तियों / तालिकाओं का संदर्भ देने में बाधा है) अनुमति नहीं हैं)। क्या आप एक उदाहरण पोस्ट कर सकते हैं जहां एक सीटीई एक बग प्रदर्शित करता है जो टेम्प टेबल के बराबर नहीं है?
onedaywhen
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.