उपश्रेणियाँ बनाम जुड़ती हैं


158

मैंने एक एप्लिकेशन के एक धीमे सेक्शन को दर्शाया, जो हमें किसी अन्य कंपनी से विरासत में मिला है जैसे कि एक उपकुंजी के बजाय एक आंतरिक जॉइन का उपयोग करने के लिए:

WHERE id IN (SELECT id FROM ...)

Refactored क्वेरी लगभग 100x तेज चलती है। (~ 50 सेकंड से ~ 0.3) मुझे सुधार की उम्मीद थी, लेकिन क्या कोई समझा सकता है कि यह इतना कठोर क्यों था? जहां क्लॉज में इस्तेमाल किए गए कॉलम सभी अनुक्रमित थे। क्या SQL क्वेरी को पंक्ति या कुछ के अनुसार एक बार खंड में निष्पादित करता है?

अपडेट - परिणाम स्पष्ट करें:

अंतर "जहां आईडी में ()" क्वेरी के दूसरे भाग में है -

2   DEPENDENT SUBQUERY  submission_tags ref st_tag_id   st_tag_id   4   const   2966    Using where

शामिल होने के साथ बनाम 1 अनुक्रमित पंक्ति:

    SIMPLE  s   eq_ref  PRIMARY PRIMARY 4   newsladder_production.st.submission_id  1   Using index


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

@simhumileco यह कोई सुधार नहीं है, यह कोई अंतर नहीं है, यह लेखक ने जो लिखा है उसके विपरीत है और कोड शैली के लिए उस तरह का संपादन अनुचित है। मुझे कोड बनाने के लिए संपादन कब करना चाहिए?
फिलीपिसे

हाय @philipxy, मैंने लेखक के विचार में हस्तक्षेप करने का इरादा नहीं किया, लेकिन केवल कोड के टुकड़े को अधिक पठनीय और अधिक सावधानी से लिखा गया।
सिम्हुमेलेको

जवाबों:


160

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

लेकिन, हाँ, व्याख्या-योजना आपको गंदे विवरण देगी।


3
कृपया ध्यान दें कि DEPENDENT SUBQUERYइसका अर्थ "सहसंबद्ध उपश्रेणी" के समान है।
तिमो

38

आप हर पंक्ति के लिए एक बार सबक्वेरी चला रहे हैं, जबकि जॉइन इंडेक्स पर होता है।


5
मुझे नहीं लगता कि यह सच है। SQL इंजन को केवल एक बार उपकुंजी चलाना चाहिए और परिणाम को सूची के रूप में उपयोग करना चाहिए।
डेराकोट

8
यह निर्भर करता है - अगर उपकुंजी किसी भी तरह से बाहरी क्वेरी (इसके डेटा का उपयोग करता है) के साथ सहसंबद्ध है, तो इसे प्रत्येक पंक्ति के साथ निष्पादित किया जाता है।
क्यूबेक

4
यह शायद इस उदाहरण में सच है, लेकिन यह सामान्य रूप से सच नहीं है।
एमी बी

1
ओपी का EXPLAINकहना है DEPENDENT SUBQUERY, जो इस व्यवहार का सबसे स्पष्ट संकेतक है।
तिमो

16

MySQL 6.0 में सबक्वेरी का मूल्यांकन कैसे किया जाता है, इसका एक उदाहरण यहां दिया गया है

नया ऑप्टिमाइज़र इस तरह की उपश्रेणियों को जोड़ में बदल देगा।


यह MySQL 6.0 पर बेहतर लेख है। आशावादी, धन्यवाद
आग कौवा

7

प्रत्येक संस्करण पर व्याख्या-योजना चलाएं, यह आपको बताएगा कि क्यों।


6

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

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


4

प्रत्येक क्वेरी के लिए क्वेरी योजना देखें।

कहाँ में और शामिल हों सकते हैं आम तौर पर एक ही निष्पादन योजना का उपयोग कर लागू किया जाना है, तो आम तौर पर उन दोनों के बीच में बदलाव करने से शून्य गति-अप है।


3
Haha, I <3 Sql उस डाउन-वोट को रगड़ता है क्योंकि वे क्वेरी योजनाओं को पढ़ना नहीं जानते हैं।
एमी बी

4

ऑप्टिमाइज़र ने बहुत अच्छा काम नहीं किया। आमतौर पर वे बिना किसी अंतर के रूपांतरित हो सकते हैं और आशावादी ऐसा कर सकते हैं।


4

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


4

यह प्रश्न कुछ हद तक सामान्य है, इसलिए यहाँ एक सामान्य उत्तर है:

मूल रूप से, जब MySQL के माध्यम से सॉर्ट करने के लिए टन की पंक्तियाँ होती हैं, तो प्रश्न लंबे समय तक चलते हैं।

यह करो:

प्रत्येक क्वेरी (एक जोड, फिर सबराइडेड एक) पर एक उदाहरण चलाएँ, और यहाँ परिणाम पोस्ट करें।

मुझे लगता है कि उन प्रश्नों के बारे में MySQL की व्याख्या में अंतर देखना सभी के लिए सीखने का अनुभव होगा।


4

जहां सबक्वेरी में प्रत्येक लौटी हुई पंक्ति के लिए 1 क्वेरी चलानी होती है। भीतरी जुड़ाव सिर्फ 1 क्वेरी को चलाने के लिए है।


3

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

बस एक अनुमान के बिना विवरण लेकिन सामान्य स्थिति है।


2

एक उपश्रेणी के साथ, आपको प्रत्येक परिणाम के लिए 2 चयन का पुन: क्रियान्वयन करना होगा, और प्रत्येक निष्पादन आमतौर पर 1 पंक्ति देता है।

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


2

यह IN उपवाक्य के रूप में बहुत अधिक नहीं है, हालांकि जॉन्स कम से कम Oracle के SQL इंजन की नींव पर हैं और बहुत जल्दी चलते हैं।


1
जहां वास्तव में स्वाभाविक रूप से बुरा नहीं है।
शॉन

2

संदर्भ पुस्तिका से लिया गया ( 14.2.10.11 जोड़ के रूप में उपश्रेणियों को फिर से लिखना ):

एक LEFT [OUTER] जोइन एक बराबर उपकेंद्र की तुलना में तेज़ हो सकता है क्योंकि सर्वर इसे बेहतर रूप से अनुकूलित करने में सक्षम हो सकता है - एक ऐसा तथ्य जो केवल MySQL सर्वर के लिए विशिष्ट नहीं है।

इसलिए उपश्रेणियाँ LEFT [OUTER] JOINS की तुलना में धीमी हो सकती हैं।

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