2009-07-08 9 views
6

संग्रहीत प्रक्रिया या दृश्य के अंत में जुड़ने की लंबी सूची के बजाय, इन-लाइन में शामिल होने के प्रभाव में, टी-एसक्यूएल में कोड को बहुत पसंद करना पसंद है।आंतरिक जुड़ने के कोडिंग के दो तरीके कौन से तेज़ हैं?

उदाहरण के लिए, मैं कोड:

SELECT  PKey , Billable, 
    (SELECT LastName FROM Contact.dbo.Contacts WHERE (Pkey = Contacts_PKey)), 
    (SELECT Description FROM Common.dbo.LMain WHERE (PKey= DType)), 
    (SELECT TaskName FROM Common.dbo.LTask WHERE (PKey = TaskType)) , 
    StartTime, EndTime, SavedTime 
FROM dbo.TopicLog where StartTime > '7/9/09' ORDER BY StartTime 

से

SELECT t.PKey, t.Billable, c.LastName, m.Description, lt.TaskName, t.StartTime, t.EndTime, t.SavedTime 
FROM dbo.TopicLog AS t  
inner join Contact.dbo.Contacts as c on c.Pkey = t.Contacts_PKey and t.StartTime > '7/9/09' 
inner join Common.dbo.LMain as m on m.PKey = t.DType 
inner join Common.dbo.LTask as lt on lt.PKey = t.TaskType 
ORDER BY t.StartTime 

मैं वाक्य रचना के इस प्रकार पसंद करते हैं क्योंकि यह इतना कम भ्रामक है जब लिख रहे हैं या डीबगिंग, खासकर जब वहाँ कई तालिकाओं हैं बल्कि शामिल होने या अन्य सामान चल रहा है (केस स्टेटमेंट्स, टी-एसक्यूएल फ़ंक्शंस, स्वयं जॉइन इत्यादि)

लेकिन मेरा सवाल है - डाटाबेस से पूछकर प्रदर्शन प्रदर्शन कर रहा हूं इस तरह से।

मेरे पास अभी तक कोई अंतर मापने में सक्षम होने के लिए एकत्रित पर्याप्त डेटा नहीं है, लेकिन मैं सड़क पर कुछ बिंदु पर जाऊंगा।

मैं आगे बढ़ने से पहले पता लगाना चाहता हूं। मैं बाद में वापस जाना नहीं चाहता और प्रदर्शन में सुधार के लिए सब कुछ रिकोड करना चाहता हूं।

उत्तर

20

दूसरा (वास्तविक आंतरिक शामिल) आमतौर पर। पहली पंक्ति (सबक्वायरीज़) प्रत्येक पंक्ति के लिए 3 प्रश्न करती है, लेकिन आमतौर पर इसे संकलक द्वारा प्रबंधित किया जाता है ताकि मतभेद कम हो जाएं।

सर्वश्रेष्ठ अभी तक: Check the query execution plans अपने लिए!

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

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

+1

+1। जैसा कि आप इंगित करते हैं, विचारशील अनुक्रमण से होने वाली जीत महत्वपूर्ण लाभ पैदा करने की अधिक संभावना है। (लेकिन निष्पादन योजना की जांच करने से उन्हें निश्चित रूप से पता चल जाएगा!) – Beska

+2

+1 "अपने लिए क्वेरी निष्पादन योजनाएं जांचें!" यह सुनिश्चित करने का एकमात्र तरीका है। ऑप्टिमाइज़र * हो सकता है * उन्हें स्वचालित रूप से आपके लिए जॉइन में बदल दें। हालांकि, दो प्रश्न बिल्कुल समान नहीं हैं। # 1 एक बाएं जॉइन है, # 2 एक इंटर्न जॉइन है। इसलिए वे आपको अलग-अलग योजनाएं देंगे। – beach

+0

यह काफी भ्रामक है - यह एक आम गलतफहमी है कि आपके द्वारा दिए गए कारणों के लिए सबक्वायरी धीमी हैं, जहां वास्तव में एसक्यूएल सर्वर पुनर्मूल्यांकन के दौरान जहां भी संभव हो वहां जुड़ने के रूप में उपक्विरी को फिर से लिखता है। – Justin

0

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

+0

बस असत्य - अक्सर SQL सर्वर निष्पादन पेड़ में subqueries पारदर्शी है जो एक शामिल द्वारा उत्पादित एक के समान है। – Justin

10

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

3

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

दूसरा उदाहरण सामान्य दिखता है।

SELECT t.PKey, t.Billable, 
c.LastName, m.Description, lt.TaskName, 
t.StartTime, t.EndTime, t.SavedTime 
FROM 
dbo.TopicLog as t, Contact.dbo.Contacts as c, 
Common.dbo.LMain as m, Common.dbo.LTask as lt 
WHERE c.Pkey = t.Contacts_PKey and t.StartTime > '7/9/09' 
    AND m.PKey = t.DType 
    AND lt.PKey = t.TaskType 
ORDER BY t.StartTime 

और एक अनुमान में यह करने के लिए आधुनिक "आंतरिक क्षेत्र पर तालिका में शामिल होने के" बराबर है वाक्य रचना:

आपको पता होना चाहिए कि भीतर करने का ओल्ड-स्कूल रास्ता मिलती है इस तरह है एक बार इसे पार्स किया गया है।

जैसा कि अन्य उत्तर कहता है, यदि आप तेजी से पूछताछ की तलाश में हैं, तो सबसे पहले यह जांचना है कि टेबल 'इंडेक्स को हल किया गया है। फिर क्वेरी निष्पादन योजना देखें।

+0

ऐसा लगता है कि इस वाक्यविन्यास के बाद वह क्या है। इंडेक्स या कोई भी इंडेक्स जो प्रत्येक पंक्ति तालिका के लिए चयन किया जा रहा है, से भी छोटी तालिका के लिए धीमा होने वाला है (जैसे 4000 पंक्तियों से अधिक)। – Jon

0

बहुत सारे SQL प्रोग्रामर पूरी तरह से अनजान हैं कि ऑप्टिमाइज़र अक्सर जुड़ने के लिए सबक्वायरी को हल करता है। किसी भी क्वेरी में प्रदर्शन की समस्या के लिए कोई कारण नहीं है।

निष्पादन योजना देखें!

1

ओपी में दो प्रश्नों बहुत अलग बातें कहते हैं और केवल एक ही परिणाम का उत्पादन करता है, तो सही डेटा मॉडल मान्यताओं स्थान पर हैं:

  1. देखने में प्रयोग किया जाता स्तंभों में से प्रत्येक नहीं अशक्त की कमी है और विदेशी कुंजी बाधाओं।

  2. प्राथमिक कुंजी या लुकअप टेबल की अनूठी कुंजी का उपयोग किया जाता है।

यह ओपी विशेष मामले के इन मान्यताओं सत्य हैं में हो सकता है लेकिन सामान्य मामले में इन अलग हैं।

जैसा कि अन्य ने इंगित किया है, उप क्वेरी एक बाहरी शामिल होने की तरह है, यह पंक्तियों को पूरी तरह से फ़िल्टर करने के बजाय अंतिम नाम, विवरण और कार्यनाम कॉलम के लिए एक शून्य वापस देगी।

इसके अतिरिक्त, अगर सबक्वायरी में से एक पंक्ति से अधिक पंक्तियां लौटाती है, तो आपको एक त्रुटि मिल जाएगी।

जहां तक ​​व्यक्तिगत वरीयता है, मैं वाक्यविन्यास में शामिल होने के साथ दूसरा उदाहरण पसंद करता हूं, लेकिन यह व्यक्तिपरक है।

0

मुझे लगता है कि दूसरा एक और अधिक तेज़ी से निष्पादित होता है। इसके पीछे कारण आपके उदाहरण में उपनाम (टी, सी, एम इत्यादि) का उपयोग कर है। नाम संबंध इंजन आसानी से तालिका स्थान पर सूचक को ढूंढ सकता है।

मुझे लगता है कि यह एसक्यूएल चौंकाने वाली युक्तियों में से एक है।

1

सामान्यतया वहाँ सरल सबक्वेरी के प्रदर्शन में है कोई फर्क नहीं बनाम मिलती है - यह एक आम धारणा है कि सबक्वेरी बहुत धीमी (क्योंकि एसक्यूएल सर्वर आंतरिक क्वेरी लूप करने के लिए है) कर रहे हैं है, लेकिन आम तौर पर यह बोल है बस असत्य! संकलन प्रक्रिया के दौरान SQL सर्वर एक निष्पादन पेड़ उत्पन्न करता है, और अक्सर इन पेड़ों में subqueries शामिल होने के बराबर हैं।

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

SELECT t.PKey, t.Billable, c.LastName, m.Description, lt.TaskName, t.StartTime, t.EndTime, t.SavedTime 
FROM dbo.TopicLog AS t  
LEFT OUTER JOIN Contact.dbo.Contacts as c on c.Pkey = t.Contacts_PKey 
LEFT OUTER JOIN Common.dbo.LMain as m on m.PKey = t.DType 
LEFT OUTER JOIN Common.dbo.LTask as lt on lt.PKey = t.TaskType 
WHERE t.StartTime > '7/9/09' 
ORDER BY t.StartTime 

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

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

संबंधित मुद्दे