बनाम उप-क्वेरी में शामिल हों


835

मैं एक पुराने स्कूल MySQL उपयोगकर्ता हूं और हमेशा JOINउप-क्वेरी पर प्राथमिकता दी है । लेकिन आजकल हर कोई सब-क्वेरी का उपयोग करता है, और मुझे इससे नफरत है; मुझे पता नहीं क्यों।

अगर कोई अंतर है तो मुझे अपने लिए न्याय करने के लिए सैद्धांतिक ज्ञान की कमी है। क्या उप-प्रश्न उतना ही अच्छा है JOINऔर इसलिए चिंता की कोई बात नहीं है?


23
उपश्रेणियाँ कभी-कभी महान होती हैं। वे MySQL में प्रदर्शन-वार चूसते हैं। उनका उपयोग न करें।
रनवे

8
मैं हमेशा इस धारणा के अधीन था कि उप-प्रश्नों को संक्षेप में डीबी प्रौद्योगिकियों में उपलब्ध जहां निष्पादन के रूप में निष्पादित किया गया था।
केजर

18
उप प्रश्न हमेशा चूसना नहीं करते हैं, जब बहुत बड़ी तालिकाओं के साथ जुड़ते हैं, तो पसंदीदा तरीका उस बड़ी तालिका (पंक्तियों की संख्या को सीमित करना) से एक उप-चयन करना है और फिर जुड़ना है।
ovais.tariq

136
"आजकल हर कोई उप-क्वेरी का उपयोग करता है" [उद्धरण वांछित]
पिस्कवर ने 7

3
संभावित रूप से संबंधित (हालांकि अधिक विशिष्ट): stackoverflow.com/questions/141278/subqueries-vs-joins/…
Leigh Brenecki

जवाबों:


190

MySQL मैनुअल से लिया गया ( 13.2.10.11 जोड़ के रूप में उपश्रेणियों को फिर से लिखना ):

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

इसलिए उपश्रेणी की तुलना में धीमी हो सकती है LEFT [OUTER] JOIN, लेकिन मेरी राय में उनकी ताकत थोड़ी अधिक पठनीयता है।


45
@ user1735921 IMO यह निर्भर करता है ... आम तौर पर, यह कोड की पठनीयता बहुत महत्वपूर्ण है, क्योंकि बाद के प्रबंधन के लिए इसका बहुत महत्व है ... आइए डोनाल्ड नथ के प्रसिद्ध कथन को याद करें: "समय से पहले का अनुकूलन सभी का मूल है प्रोग्रामिंग में बुराई (या कम से कम अधिकांश) । हालांकि, स्वाभाविक रूप से ऐसे प्रोग्रामिंग क्षेत्र हैं जहां प्रदर्शन सर्वोपरि है ... आदर्श रूप से, जब कोई एक दूसरे के साथ सामंजस्य स्थापित करने में सफल होता है :)
simhumileco

30
अधिक जटिल प्रश्नों में, मुझे उप-प्रश्नों की तुलना में पढ़ने में बहुत आसान लगता है। उप-प्रश्न मेरे सिर में नूडल्स के कटोरे में बदल जाते हैं।
ज़हरा

6
@ user1735921 यकीन है, खासकर जब क्वेरी इतनी जटिल हो जाती है कि यह गलत काम करता है और आप इसे ठीक करने में एक दिन बिताते हैं ... हमेशा की तरह बीच में एक संतुलन होता है।
fabio.sussetto

6
@ user1735921 केवल अगर प्रदर्शन लाभ भविष्य में आवश्यक रखरखाव समय में वृद्धि के लायक है
जोशुआ Schlichting

3
मेरी राय Joinऔर sub queryअलग वाक्यविन्यास हैं, इसलिए पठनीयता की हम तुलना नहीं कर सकते, दोनों में उच्च पठनीयता है जब तक आप SQL सिंटैक्स में अच्छे हैं। प्रदर्शन अधिक महत्वपूर्ण है।
थवप्रकाश स्वामीनाथन

840

फॉर्म की समस्याओं को हल करने के लिए उप-क्वेरी तार्किक रूप से सही तरीका है, "ए से तथ्य प्राप्त करें, बी से तथ्यों पर सशर्त"। ऐसे उदाहरणों में, बी को उप-क्वेरी में शामिल करने की तुलना में अधिक तार्किक समझ में आता है। यह एक व्यावहारिक अर्थ में भी सुरक्षित है, क्योंकि आपको बी से कई मैचों के कारण ए से डुप्लिकेट तथ्यों को प्राप्त करने के बारे में सतर्क रहने की आवश्यकता नहीं है।

व्यावहारिक रूप से, हालांकि, जवाब आमतौर पर प्रदर्शन के लिए नीचे आता है। कुछ ऑप्टिमाइज़र नींबू को एक बनाम क्वेरी से जोड़कर देखते हैं, और कुछ दूसरे तरीके से नींबू चूसते हैं, और यह ऑप्टिमाइज़र-विशिष्ट, DBMS- संस्करण-विशिष्ट और क्वेरी-विशिष्ट है।

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


105
बहुत बढ़िया जवाब। मैं यह भी जोड़ूंगा कि डेवलपर्स (esp। शौकिया वाले) हमेशा SQL में कुशल नहीं होते हैं।
अल्वारो गोंजालेज

4
+1 लंबे समय तक इस मुद्दे के लिए कुछ तार्किक स्पष्टीकरण की तलाश में, यह केवल एक ही उत्तर है जो मेरे लिए तर्कसंगत लगता है
अली उमैर

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

6
@JinghuiNiu ग्राहक जिन्होंने महंगा सामान खरीदा select custid from cust join bought using (custid) where price > 500:। यदि किसी ग्राहक ने कई महंगी वस्तुएँ खरीदी हैं, तो आपको दोगुना मिलेगा। इसे ठीक करने के select custid from cust where exists (select * from bought where custid = cust.custid and price > 500)। आप select distinct …इसके बजाय उपयोग कर सकते हैं , लेकिन यह अक्सर अधिक काम होता है, या तो अनुकूलक या मूल्यांकनकर्ता के लिए।
मार्सेलो कैंटोस

1
@MatTheWhale हाँ मैंने एक ओवरसाइप्लाइज़्ड उत्तर का उपयोग किया था coz I मैं आलसी था। एक वास्तविक परिदृश्य में आप हिरासत से सिर्फ कस्टिड से अधिक कॉलम खींच रहे होंगे।
मार्सेलो कैंटोस

357

ज्यादातर मामलों में JOINउप-प्रश्नों की तुलना में तेज़ होते हैं और उप-क्वेरी के लिए तेज़ होना बहुत दुर्लभ है।

में JOINरों आरडीबीएमएस एक कार्य योजना लागू करके आपकी क्वेरी के लिए बेहतर है बना सकते हैं और भविष्यवाणी कर सकते हैं कि कौन सा डेटा संसाधित करने के लिए लोड किया जाना चाहिए और उप क्वेरी जहां यह सभी प्रश्नों चलाने के लिए और प्रसंस्करण करने के लिए अपने सभी डेटा लोड होगा विपरीत समय बचाने, ।

उप-प्रश्नों में अच्छी बात यह है कि वे JOINएस की तुलना में अधिक पठनीय हैं : यही कारण है कि अधिकांश नए एसक्यूएल लोग उन्हें पसंद करते हैं; यह आसान तरीका है; लेकिन जब प्रदर्शन की बात आती है, तो JOINS ज्यादातर मामलों में बेहतर होते हैं, हालांकि उन्हें पढ़ना भी मुश्किल नहीं है।


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

16
यह उत्तर उस प्रश्न के लिए थोड़ा सा सरल है जो पूछा गया था। जैसा कि आप कहते हैं: कुछ उपश्रेणी ठीक हैं और कुछ निश्चित नहीं हैं। उत्तर वास्तव में दोनों को अलग करने में मदद नहीं करता है। (यह भी 'बहुत दुर्लभ' वास्तव में आपके डेटा / ऐप पर निर्भर करता है)।
कारण

21
क्या आप प्रलेखन संदर्भ या परीक्षण परिणामों के साथ अपने किसी भी बिंदु को साबित कर सकते हैं?
उउर गुम्मशान

62
मैंने उप-प्रश्नों के साथ बहुत अच्छे अनुभव किए, जिनमें ऊपरी क्वेरी का बैक-रेफरेंस है, खासकर जब यह 100,000 से ऊपर की पंक्ति-गणना के लिए आता है। बात स्मृति उपयोग और स्वैप-फ़ाइल में पेजिंग की लगती है। एक जुड़ने से बहुत बड़ी मात्रा में डेटा उत्पन्न होता है, जो स्मृति में फिट नहीं हो सकता है और इसे स्वैप-फ़ाइल में पृष्ठांकित किया जाना चाहिए। जब भी ऐसा होता है तो छोटे उप-चयनों का क्वेरी-टाइम select * from a where a.x = (select b.x form b where b.id = a.id)एक जॉइन की तुलना में बेहद छोटा होता है। यह एक बहुत ही विशिष्ट समस्या है, लेकिन कुछ मामलों में यह आपको घंटों से मिनटों तक पहुंचाती है।
१२

13
मैं ओरेकल के साथ अनुभव कर रहा हूं और मैं कह सकता हूं, अगर आपके पास कोई फ़िल्टरिंग या छांटना नहीं है, तो उप-प्रश्न बड़ी तालिकाओं पर बहुत बेहतर हैं।
अमीर पाशाज़ादेह

130

अपने डेटा पर क्वेरी को कैसे निष्पादित करता है, यह देखने के लिए EXPLAIN का उपयोग करें। इस जवाब में एक विशाल "यह निर्भर करता है" ...

PostgreSQL एक सबक्वेरी को एक ज्वाइन या फिर एक सबक्वेरी में तब सम्मिलित कर सकता है जब उसे लगता है कि एक दूसरे से तेज है। यह सब डेटा, इंडेक्स, सहसंबंध, डेटा की मात्रा, क्वेरी आदि पर निर्भर करता है।


6
यही कारण है कि postgresql इतना अच्छा और उपयोगी है कि यह समझता है कि लक्ष्य क्या है और यह जो बेहतर है उसके आधार पर एक क्वेरी तय करेगा और postgresql अपने डेटा को देखने के लिए जानने में बहुत अच्छा है
WojonsTech

heww। मुझे लगता है कि मेरे लिए प्रश्नों के टन को फिर से लिखने की कोई आवश्यकता नहीं है! जीत के लिए postgresql।
डैनियल शिन

77

वर्ष २०१० में मैं इस प्रश्न के लेखक में शामिल हो गया और जोरदार तरीके से मतदान किया JOIN, लेकिन बहुत अधिक अनुभव (विशेषकर MySQL में) मैं यह बता सकता हूं: हां उपश्रेणी बेहतर हो सकती है। मैंने यहाँ कई उत्तर पढ़े हैं; कुछ उपश्रेणियाँ तेज हैं, लेकिन इसमें एक अच्छी व्याख्या का अभाव है। मुझे आशा है कि मैं इस (बहुत) देर से जवाब के साथ एक प्रदान कर सकता हूं:

सबसे पहले, मुझे सबसे महत्वपूर्ण कहना चाहिए: उप-प्रश्नों के विभिन्न रूप हैं

और दूसरा महत्वपूर्ण कथन: आकार मायने रखता है

यदि आप उप-क्वेरी का उपयोग करते हैं, तो आपको पता होना चाहिए कि DB-Server उप-क्वेरी को कैसे निष्पादित करता है। विशेष रूप से अगर उप-क्वेरी का मूल्यांकन एक बार या प्रत्येक पंक्ति के लिए किया जाता है! दूसरी तरफ, एक आधुनिक डीबी-सर्वर बहुत कुछ अनुकूलन करने में सक्षम है। कुछ मामलों में एक सबक्वेरी एक क्वेरी को अनुकूलित करने में मदद करती है, लेकिन DB-Server का एक नया संस्करण अनुकूलन को अप्रचलित बना सकता है।

चयन-फ़ील्ड में उप-प्रश्न

SELECT moo, (SELECT roger FROM wilco WHERE moo = me) AS bar FROM foo

ध्यान रखें कि प्रत्येक परिणामी पंक्ति से एक उप-क्वेरी निष्पादित की जाती है foo
यदि संभव हो तो इससे बचें; यह भारी डेटासेट पर आपकी क्वेरी को बहुत धीमा कर सकता है। हालाँकि, यदि उप-क्वेरी में इसका कोई संदर्भ नहीं है, तो fooइसे DB- सर्वर द्वारा स्थिर सामग्री के रूप में अनुकूलित किया जा सकता है और केवल एक बार मूल्यांकन किया जा सकता है।

जहाँ-जहाँ कथन में उप-प्रश्न

SELECT moo FROM foo WHERE bar = (SELECT roger FROM wilco WHERE moo = me)

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

ज्वाइन-स्टेटमेंट में उप-प्रश्न

SELECT moo, bar 
  FROM foo 
    LEFT JOIN (
      SELECT MIN(bar), me FROM wilco GROUP BY me
    ) ON moo = me

यह दिलचस्प है। हम JOINएक उप-क्वेरी के साथ गठबंधन करते हैं। और यहां हमें उप-प्रश्नों की असली ताकत मिलती है। लाखों पंक्तियों के साथ एक डेटासेट की कल्पना करें, wilcoलेकिन केवल कुछ अलग me। एक विशाल तालिका के खिलाफ शामिल होने के बजाय, हमारे पास अब एक छोटी अस्थायी तालिका है, जिसके खिलाफ जुड़ने के लिए। यह डेटाबेस आकार के आधार पर बहुत तेजी से प्रश्नों का परिणाम दे सकता है। आप के साथ एक ही प्रभाव हो सकता है CREATE TEMPORARY TABLE ...और INSERT INTO ... SELECT ..., जो बहुत ही जटिल प्रश्नों पर बेहतर पठनीयता प्रदान कर सकता है (लेकिन बार-बार पढ़ने वाले अलगाव में डेटासेट को लॉक कर सकता है)।

नेस्टेड सब-क्वेरीज़

SELECT moo, bar
  FROM (
    SELECT moo, CONCAT(roger, wilco) AS bar
      FROM foo
      GROUP BY moo
      HAVING bar LIKE 'SpaceQ%'
  ) AS temp_foo
  ORDER BY bar

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

निष्कर्ष

उप-क्वेरीज़ के लिए कोई प्रतिस्थापन नहीं है JOINऔर आपको उन्हें इस तरह (हालांकि संभव हो) का उपयोग नहीं करना चाहिए। मेरी विनम्र राय में, एक उप-क्वेरी का सही उपयोग त्वरित प्रतिस्थापन के रूप में उपयोग होता है CREATE TEMPORARY TABLE ...। एक अच्छी उप-क्वेरी एक डाटासेट को कम करती है जिस तरह से आप एक के ONबयान में पूरा नहीं कर सकते हैं JOIN। यदि किसी सब-क्वेरी में कीवर्ड्स में से एक है GROUP BYया DISTINCTअधिमानतः चुनिंदा फ़ील्ड्स या जहां स्टेटमेंट में स्थित नहीं है, तो यह प्रदर्शन में बहुत सुधार कर सकता है।


3
के लिए Sub-queries in the Join-statement: (1) उप-क्वेरी से व्युत्पन्न तालिका स्वयं उत्पन्न करने में बहुत लंबा समय लग सकता है। (2) परिणामी व्युत्पन्न तालिका अनुक्रमित नहीं है। ये दोनों अकेले SQL को धीमा कर सकते हैं।
जेंक

@jxc मैं केवल MySQL के लिए बोल सकता हूं (1) वहां यह एक अस्थायी तालिका है जो एक जॉइन के समान है। समय डेटा की मात्रा पर निर्भर करता है। यदि आप एक सबक्वेरी के साथ डेटा को कम नहीं कर सकते हैं, तो एक जॉइन का उपयोग करें। (2) यह सही है, यह उस कारक पर निर्भर करता है जिससे आप अस्थायी तालिका में डेटा को कम कर सकते हैं। मेरे पास वास्तविक दुनिया के मामले थे, जहां मैं सम्मिलित आकार को कुछ सौ से कुछ सौ तक कम कर सकता था और एक उप-वर्ग के साथ एक सेकंड के एक चौथाई तक (पूर्ण सूचकांक उपयोग के साथ) क्वेरी के समय को कम कर सकता था।
ट्रेंडफिशर

IMO: (1) ऐसी अस्थायी तालिका (व्युत्पन्न तालिका) को भौतिक नहीं किया जाता है, इस प्रकार हर बार जब आप SQL चलाते हैं, तो अस्थायी तालिका को फिर से बनाया जाना चाहिए, जो बहुत महंगा हो सकता है और एक वास्तविक बोतल-गर्दन (यानी लाखों पर समूह बनाकर चल सकता है) अभिलेखों का) (2) भले ही आप 10टेम्‍प-टेबल के आकार को रिकॉर्ड में कम कर सकते हैं , क्योंकि कोई सूचकांक नहीं है, इसका मतलब है कि अभी भी संभावित रूप से w / o टेम्‍प टेबल की तुलना में 9 गुना अधिक डेटा रिकॉर्ड क्वेरी करने के लिए है जब अन्‍य टेबलों को शामिल किया जा रहा है। BTW मैं इस मामले में मेरे db (MySQL) के साथ पहले था, मेरे मामले में, उप-क्वेरी का उपयोग करके SELECT listबहुत तेजी से हो सकता है।
जेंक

@jxc मुझे संदेह नहीं है कि बहुत सारे उदाहरण हैं, जहां एक उपश्रेणी का उपयोग कम इष्टतम है। अच्छे अभ्यास के रूप में आपको EXPLAINअनुकूलन से पहले एक क्वेरी पर उपयोग करना चाहिए । पुराने के साथ set profiling=1आप आसानी से देख सकते हैं, अगर एक अस्थायी तालिका एक अड़चन है। और यहां तक ​​कि एक सूचकांक को प्रसंस्करण समय की आवश्यकता होती है, बी-ट्रीज़ रिकॉर्ड के लिए क्वेरी का अनुकूलन करते हैं, लेकिन 10 रिकॉर्ड तालिका लाखों रिकॉर्ड के लिए एक सूचकांक से बहुत तेज़ हो सकती है। लेकिन यह क्षेत्र के आकार और प्रकार जैसे कई कारकों पर निर्भर करता है।
ट्रेंडफिशर

1
मैं वास्तव में आपके स्पष्टीकरण का आनंद लिया। धन्यवाद।
अपरिपक्वगूड

43

सब से पहले, दो की तुलना करने के लिए आपको सबक्वेरी के साथ प्रश्नों को अलग करना चाहिए:

  1. उपवर्गों का एक वर्ग जिसमें हमेशा समतुल्य समान क्वेरी जोड़ के साथ लिखी जाती है
  2. उपवर्गों का एक वर्ग जो जोड़ का उपयोग करके फिर से नहीं लिखा जा सकता है

प्रथम श्रेणी के लिएप्रश्नों के लिए एक अच्छा RDBMS समान रूप से जोड़ और उपश्रेणियों को देखेगा और समान क्वेरी प्लान तैयार करेगा।

इन दिनों भी mysql यही करता है।

फिर भी, कभी-कभी यह नहीं होता है, लेकिन इसका मतलब यह नहीं है कि जॉन्स हमेशा जीतेंगे - मेरे पास ऐसे मामले थे जब mysql में सबक्वेरी का उपयोग करके बेहतर प्रदर्शन किया गया था। (उदाहरण के लिए, अगर वहाँ सही ढंग से लागत का अनुमान लगाने के लिए mysql योजनाकार को रोकने के लिए कुछ है और यदि योजनाकार जॉइन-वैरिएंट और सबक्वेरी-वैरिएंट को नहीं देखता है, तो उप-वर्ग एक निश्चित पथ को मजबूर करके जॉइनर्स को बेहतर बना सकते हैं)।

निष्कर्ष यह है कि यदि आप सुनिश्चित करना चाहते हैं कि कौन सा बेहतर प्रदर्शन करेगा, तो आपको अपने सवालों से जुड़ना चाहिए।

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


1
क्या आप उप-प्रश्नों का उपयोग करके लिखी गई क्वेरी का एक उदाहरण प्रदान कर सकते हैं जिसे जॉइन में परिवर्तित नहीं किया जा सकता (दूसरी कक्षा, जैसा कि आप इसे कहते हैं)?
ज़हरा

24

मुझे लगता है कि उद्धृत उत्तरों में जो बात पर जोर दिया गया है, वह डुप्लिकेट का मुद्दा है और समस्याग्रस्त परिणामों जो विशिष्ट (उपयोग) मामलों से उत्पन्न हो सकता है।

(हालांकि मार्सेलो कैंटोस इसका उल्लेख करता है)

मैं SQL पर स्टैनफोर्ड के लगुनिटा पाठ्यक्रमों से उदाहरण का हवाला दूंगा।

छात्र की मेज

+------+--------+------+--------+
| sID  | sName  | GPA  | sizeHS |
+------+--------+------+--------+
|  123 | Amy    |  3.9 |   1000 |
|  234 | Bob    |  3.6 |   1500 |
|  345 | Craig  |  3.5 |    500 |
|  456 | Doris  |  3.9 |   1000 |
|  567 | Edward |  2.9 |   2000 |
|  678 | Fay    |  3.8 |    200 |
|  789 | Gary   |  3.4 |    800 |
|  987 | Helen  |  3.7 |    800 |
|  876 | Irene  |  3.9 |    400 |
|  765 | Jay    |  2.9 |   1500 |
|  654 | Amy    |  3.9 |   1000 |
|  543 | Craig  |  3.4 |   2000 |
+------+--------+------+--------+

तालिका लागू करें

(विशिष्ट विश्वविद्यालयों और बड़ी कंपनियों के लिए किए गए आवेदन)

+------+----------+----------------+----------+
| sID  | cName    | major          | decision |
+------+----------+----------------+----------+
|  123 | Stanford | CS             | Y        |
|  123 | Stanford | EE             | N        |
|  123 | Berkeley | CS             | Y        |
|  123 | Cornell  | EE             | Y        |
|  234 | Berkeley | biology        | N        |
|  345 | MIT      | bioengineering | Y        |
|  345 | Cornell  | bioengineering | N        |
|  345 | Cornell  | CS             | Y        |
|  345 | Cornell  | EE             | N        |
|  678 | Stanford | history        | Y        |
|  987 | Stanford | CS             | Y        |
|  987 | Berkeley | CS             | Y        |
|  876 | Stanford | CS             | N        |
|  876 | MIT      | biology        | Y        |
|  876 | MIT      | marine biology | N        |
|  765 | Stanford | history        | Y        |
|  765 | Cornell  | history        | N        |
|  765 | Cornell  | psychology     | Y        |
|  543 | MIT      | CS             | N        |
+------+----------+----------------+----------+

आइए उन छात्रों के लिए GPA स्कोर खोजने की कोशिश करें जिन्होंने CSप्रमुख (विश्वविद्यालय की परवाह किए बिना) आवेदन किया है

एक उपश्रेणी का उपयोग करना:

select GPA from Student where sID in (select sID from Apply where major = 'CS');

+------+
| GPA  |
+------+
|  3.9 |
|  3.5 |
|  3.7 |
|  3.9 |
|  3.4 |
+------+

इस परिणाम के लिए औसत मूल्य है:

select avg(GPA) from Student where sID in (select sID from Apply where major = 'CS');

+--------------------+
| avg(GPA)           |
+--------------------+
| 3.6800000000000006 |
+--------------------+

शामिल होने का उपयोग करना:

select GPA from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';

+------+
| GPA  |
+------+
|  3.9 |
|  3.9 |
|  3.5 |
|  3.7 |
|  3.7 |
|  3.9 |
|  3.4 |
+------+

इस परिणाम के लिए औसत मूल्य:

select avg(GPA) from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';

+-------------------+
| avg(GPA)          |
+-------------------+
| 3.714285714285714 |
+-------------------+

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

ऐसा लगता है कि कुछ मामलों में एक उप-क्वेरी किसी भी प्रदर्शन मुद्दों के अलावा, जाने का सबसे सुरक्षित तरीका है।


मुझे लगता है कि आप यहां उप-क्वेरी का उपयोग नहीं कर सकते। यह एक ऐसा मामला नहीं है जहाँ आप तार्किक रूप से या तो उपयोग कर सकते हैं, लेकिन एक गलत जवाब देता है क्योंकि इसके तकनीकी कार्यान्वयन के कारण। यह एक ऐसा मामला है जहां आप उप-क्वेरी का उपयोग नहीं कर सकते क्योंकि CS से संबंधित छात्र 3.9 स्कोर नहीं कर सकता है जो कि स्कोर की सूची में है। एक बार उप-क्वेरी निष्पादित होने पर CS का संदर्भ खो जाता है, जो कि हम तार्किक रूप से नहीं चाहते हैं। तो यह एक अच्छा उदाहरण नहीं है जहां या तो इस्तेमाल किया जा सकता है। उप-क्वेरी का उपयोग इस उपयोग-मामले के लिए वैचारिक / तार्किक रूप से गलत है, भले ही सौभाग्य से यह एक अलग डेटासेट के लिए सही परिणाम देता है।
सौरभ पाटिल

22

SQL सर्वर के लिए MSDN दस्तावेज़ीकरण कहता है

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

इसलिए अगर आपको कुछ पसंद है

select * from t1 where exists select * from t2 where t2.parent=t1.id

इसके बजाय जुड़ने का उपयोग करने का प्रयास करें। अन्य मामलों में, इससे कोई फर्क नहीं पड़ता।

मैं कहता हूं: कार्य बनाना उप-क्षेत्रों के लिए क्लैटर की समस्या को खत्म करता है और आपको उप-वर्गों के लिए अतिरिक्त तर्क को लागू करने की अनुमति देता है। इसलिए मैं जब भी संभव हो उपकेंद्रों के लिए कार्य बनाने की सलाह देता हूं।

कोड में अव्यवस्था एक बड़ी समस्या है और उद्योग दशकों से इसे टालने पर काम कर रहा है।


9
कुछ आरडीबीएमएस (जैसे ओरेकल) में कार्यों के साथ उपश्रेणियों को बदलना एक बहुत बुरा विचार-प्रदर्शन-वार है, इसलिए मैं जहां भी संभव हो, कार्यों के बजाय केवल विपरीत / उप-उपयोगों का उपयोग करने की सलाह दूंगा।
फ्रैंक श्मिट

3
@FrankSchmitt कृपया संदर्भ के साथ अपने तर्क का समर्थन करें।
उउर गुम्मशान

2
ऐसे मामले भी हैं जहां आपको अस्तित्व की जाँच करने पर भी एक जुड़ाव के बजाय एक उप क्वेरी का उपयोग करना चाहिए: यदि आप जाँच करते हैं NOT EXISTS। विभिन्न कारणों NOT EXISTSसे एक जीत LEFT OUTER JOIN: पूर्वसर्गता, असफलता-सुरक्षा (अशक्त स्तंभों के मामले में) और पठनीयता। sqlperformance.com/2012/12/t-sql-queries/left-ant-semi-join
टिम शाल्टर

16

पुराने Mambo CMS से बहुत बड़े डेटाबेस पर चलाएँ:

SELECT id, alias
FROM
  mos_categories
WHERE
  id IN (
    SELECT
      DISTINCT catid
    FROM mos_content
  );

0 सेकंड

SELECT
  DISTINCT mos_content.catid,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

~ 3 सेकंड

एक उदाहरण से पता चलता है कि वे ठीक उसी पंक्तियों की संख्या की जांच करते हैं, लेकिन एक को 3 सेकंड लगते हैं और एक तत्काल के पास है। कहानी का नैतिक? यदि प्रदर्शन महत्वपूर्ण है (जब यह नहीं है?), तो इसे कई तरीके आज़माएं और देखें कि कौन सा सबसे तेज़ है।

तथा...

SELECT
  DISTINCT mos_categories.id,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

0 सेकंड

फिर से, एक ही परिणाम, समान संख्या में पंक्तियों की जांच की गई। मेरा अनुमान है कि DISTINCT mos_content.catid को DISTINCT mos_categories.id की तुलना में अधिक समय लगता है।


1
मैं इस बारे में अधिक जानना चाहूंगा कि आप अंतिम पंक्ति में क्या इंगित करने की कोशिश कर रहे हैं "मेरा अनुमान है कि DISTINCT mos_content.catid को DISTINCT mos_categories.id की तुलना में अधिक समय लगता है।" । क्या आप कह रहे हैं कि एक आईडी को केवल नाम दिया जाना चाहिए idऔर कुछ नाम नहीं दिया जाना चाहिए catid? मेरे db एक्सेस को ऑप्टिमाइज़ करने की कोशिश करना, और आपकी सीख मदद कर सकती है।
बूल.देव b

2
उस स्थिति में SQL IN का उपयोग करना एक बुरा अभ्यास है और यह कुछ भी साबित नहीं करता है।
उउर गुम्मशान

15

मेरे अवलोकन के अनुसार, दो मामलों की तरह, यदि एक तालिका में कम से कम 100,000 रिकॉर्ड हैं, तो जुड़ाव तेजी से काम करेगा।

लेकिन इस मामले में कि एक तालिका में 100,000 से अधिक रिकॉर्ड हैं तो एक उपश्रेणी सबसे अच्छा परिणाम है।

मेरे पास एक तालिका है जिसमें 500,000 रिकॉर्ड हैं जो मैंने क्वेरी के नीचे बनाए हैं और इसका परिणाम समय जैसा है

SELECT * 
FROM crv.workorder_details wd 
inner join  crv.workorder wr on wr.workorder_id = wd.workorder_id;

परिणाम: 13.3 सेकंड

select * 
from crv.workorder_details 
where workorder_id in (select workorder_id from crv.workorder)

परिणाम: 1.65 सेकंड


मैं सहमत हूं, कभी-कभी क्वेरी को तोड़ना भी काम करता है, जब आपके पास मिलियन रिकॉर्ड होते हैं, तो आप जॉइन का उपयोग नहीं करना चाहते हैं क्योंकि वे हमेशा के लिए लेते हैं। बल्कि इसे कोड में हैंडल करें और कोड में मैप बेहतर है।
user1735921 12

1
अपने जोड़ को तेजी से पर्याप्त रूप से काम नहीं कर रहे हैं, आपको एक सूचकांक याद आ रहा है। वास्तविक प्रदर्शन की तुलना में क्वेरी एनालाइज़र काफी मददगार हो सकता है।
digital.ARon

मैं अजय गजेरा से सहमत हूं, मैंने यह अपने लिए देखा है।
user1735921

14
दो प्रश्नों के प्रदर्शन की तुलना करने का कोई मतलब नहीं है जो अलग-अलग परिणाम देते हैं?
पॉल स्पीगल

हाँ, वे अलग-अलग प्रश्न हैं लेकिन एक ही परिणाम पर लौट रहे हैं
राजा नव

12

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

   SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');

ध्यान दें कि उप-क्वेरी के परिणामों पर एक सामान्य मूल्य ऑपरेटर का उपयोग करने के लिए आवश्यक है कि केवल एक फ़ील्ड लौटाया जाना चाहिए। यदि आप अन्य मानों के सेट के भीतर एकल मान के अस्तित्व की जाँच में रुचि रखते हैं, तो IN का उपयोग करें:

   SELECT title FROM books WHERE author_id IN (SELECT id FROM authors WHERE last_name ~ '^[A-E]');

यह स्पष्ट रूप से एक LEFT-JOIN से अलग है जहाँ आप केवल तालिका A और B से सामान जोड़ना चाहते हैं, भले ही Join-condition में तालिका B, आदि में कोई मिलान रिकॉर्ड न मिले।

यदि आप सिर्फ गति के बारे में चिंतित हैं तो आपको अपने डेटाबेस की जांच करनी होगी और एक अच्छी क्वेरी लिखनी होगी और देखना होगा कि प्रदर्शन में कोई महत्वपूर्ण अंतर है या नहीं।


11

MySQL संस्करण: 5.5.28-0ubuntu0.12.04.2-log

मैं इस धारणा के तहत था कि JOIN हमेशा MySQL में एक उप-क्वेरी से बेहतर है, लेकिन निर्णय लेने के लिए EXPLAIN एक बेहतर तरीका है। यहाँ एक उदाहरण है जहाँ उप प्रश्न JOIN से बेहतर काम करते हैं।

यहाँ 3 उप-प्रश्नों के साथ मेरी क्वेरी है:

EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
FROM `vote-ranked-listory` vrl 
INNER JOIN lists l ON l.list_id = vrl.list_id 
INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=43) IS NULL 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=55) IS NULL 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL 
ORDER BY vrl.moved_date DESC LIMIT 200;

प्रदर्शन से पता चलता है:

+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
| id | select_type        | table    | type   | possible_keys                                       | key          | key_len | ref                                             | rows | Extra                    |
+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
|  1 | PRIMARY            | vrl      | index  | PRIMARY                                             | moved_date   | 8       | NULL                                            |  200 | Using where              |
|  1 | PRIMARY            | l        | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
|  1 | PRIMARY            | vrlih    | eq_ref | PRIMARY                                             | PRIMARY      | 9       | ranker.vrl.list_id,ranker.vrl.ontology_id,const |    1 | Using where              |
|  1 | PRIMARY            | lbs      | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
|  4 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
|  3 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+

JOINs के साथ एक ही प्रश्न है:

EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
FROM `vote-ranked-listory` vrl 
INNER JOIN lists l ON l.list_id = vrl.list_id 
INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
LEFT JOIN list_tag lt1 ON lt1.list_id = vrl.list_id AND lt1.tag_id = 43 
LEFT JOIN list_tag lt2 ON lt2.list_id = vrl.list_id AND lt2.tag_id = 55 
INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403 
WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
AND lt1.list_id IS NULL AND lt2.tag_id IS NULL 
ORDER BY vrl.moved_date DESC LIMIT 200;

और आउटपुट है:

+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                                       | key          | key_len | ref                                         | rows | Extra                                        |
+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | lt3   | ref    | list_tag_key,list_id,tag_id                         | tag_id       | 5       | const                                       | 2386 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | l     | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.lt3.list_id                          |    1 | Using where                                  |
|  1 | SIMPLE      | vrlih | ref    | PRIMARY                                             | PRIMARY      | 4       | ranker.lt3.list_id                          |  103 | Using where                                  |
|  1 | SIMPLE      | vrl   | ref    | PRIMARY                                             | PRIMARY      | 8       | ranker.lt3.list_id,ranker.vrlih.ontology_id |   65 | Using where                                  |
|  1 | SIMPLE      | lt1   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index; Not exists         |
|  1 | SIMPLE      | lbs   | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                          |    1 | Using where                                  |
|  1 | SIMPLE      | lt2   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index                     |
+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+

rowsकॉलम की तुलना अंतर को बताती है और JOINs के साथ क्वेरी का उपयोग कर रही हैUsing temporary; Using filesort

बेशक, जब मैं दोनों प्रश्नों को चलाता हूं, तो पहला 0.02 सेकंड में किया जाता है, दूसरा 1 मिनट के बाद भी पूरा नहीं होता है, इसलिए EXPLAIN ने इन प्रश्नों को ठीक से समझाया।

यदि मेरे पास list_tagमेज पर INNER JOIN नहीं है, तो यदि मैं हटा दूं

AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL  

पहली क्वेरी और इसके बाद:

INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403

दूसरी क्वेरी से, तब EXPLAIN दोनों प्रश्नों के लिए समान पंक्तियों को लौटाता है और ये दोनों क्वेरीज़ समान रूप से तेज़ चलती हैं।


मेरे पास भी ऐसी ही स्थिति है, लेकिन आपकी तुलना में अधिक
जुड़ाव के

Oracle या PostgreSQL में मैंने कोशिश की होगी: और EXISTS (Select 1 FROM list_tag WHERE list_id = l.list_id और tag_id में (43, 55, 246403)
डेविड

11

उपकेंद्रों में एक मक्खी पर एकत्रीकरण कार्यों की गणना करने की क्षमता है। उदा। पुस्तक का न्यूनतम मूल्य ज्ञात करें और सभी पुस्तकें प्राप्त करें जो इस मूल्य के साथ बेची जाती हैं। 1) उपश्रेणियों का उपयोग करना:

SELECT titles, price
FROM Books, Orders
WHERE price = 
(SELECT MIN(price)
 FROM Orders) AND (Books.ID=Orders.ID);

2) JOINs का उपयोग करना

SELECT MIN(price)
     FROM Orders;
-----------------
2.99

SELECT titles, price
FROM Books b
INNER JOIN  Orders o
ON b.ID = o.ID
WHERE o.price = 2.99;

एक और मामला: GROUP BYविभिन्न तालिकाओं के साथ कई एस: stackoverflow.com/questions/11415284/… उपश्रेणियों को सख्ती से अधिक सामान्य लगता है। MySQL मैन को भी देखें: dev.mysql.com/doc/refman/5.7/en/optimizing-subereries.html | dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.html
Ciro Santilli Sant 病毒 .com/ .com/

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

मैं डेविड से सहमत हूं, और आप न्यूनतम मूल्य प्राप्त करने के लिए समूह का उपयोग कर सकते हैं।
user1735921

9
  • एक सामान्य नियम यह है कि ज्यादातर मामलों (99%) में जोड़ तेजी से होते हैं।
  • अधिक डेटा टेबल में, उपश्रेणी धीमी होती है।
  • कम डेटा तालिकाओं है, सबक्वेरी के रूप में बराबर गति मिलती है
  • सबक्वेरी , सरल समझना आसान, और पढ़ने में आसान कर रहे हैं।
  • अधिकांश वेब और ऐप फ्रेमवर्क और उनके "ओआरएम" और "एक्टिव रिकॉर्ड" सबक्वेरी के साथ प्रश्न उत्पन्न करते हैं , क्योंकि उपश्रेणियों के साथ जिम्मेदारी विभाजित करना, कोड बनाए रखना, आदि आसान होते हैं।
  • छोटी वेब साइटों या ऐप्स के लिए उपश्रेणी ठीक है, लेकिन बड़ी वेब साइटों और ऐप्स के लिए आपको अक्सर क्वेरी में शामिल होने के लिए उत्पन्न प्रश्नों को फिर से लिखना होगा , विशेष रूप से अगर कोई क्वेरी में कई उपश्रेणियों का उपयोग करता है ।

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


> लेकिन यह कथन उन सरल मामलों पर लागू होता है जो मुझे समझ में आते हैं कि यह या तो एक साधारण मामला है जिसे RDBMS द्वारा "JOIN" में फिर से लिखा जा सकता है, या यह एक ऐसा जटिल मामला है कि यहाँ उपश्रेणी उपयुक्त है। :-) ORM पर अच्छा बिंदु। मुझे लगता है कि इसका सबसे बड़ा प्रभाव है।
पायलेट

4

अंतर केवल तब देखा जाता है जब दूसरी ज्वाइनिंग टेबल में प्राइमरी टेबल की तुलना में काफी अधिक डेटा होता है। मुझे नीचे जैसा अनुभव था ...

हमारे पास एक सौ हजार प्रविष्टियों की एक उपयोगकर्ता तालिका और उनकी सदस्यता डेटा (दोस्ती) के बारे में 3 सौ हजार प्रविष्टियां थीं। मित्रों और उनके डेटा को लेने के लिए यह एक सम्मिलित बयान था, लेकिन एक बड़ी देरी के साथ। लेकिन यह ठीक काम कर रहा था जहां सदस्यता तालिका में केवल थोड़ी मात्रा में डेटा था। एक बार जब हमने इसे उप-क्वेरी का उपयोग करने के लिए बदल दिया तो यह ठीक काम कर गया।

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

इसलिए मुझे लगता है कि जुड़ने और उप क्वेरी स्टेटमेंट ठीक काम कर रहे हैं और यह डेटा और स्थिति पर निर्भर करता है।


3

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


1

मैं बस एक ही समस्या के बारे में सोच रहा हूं, लेकिन मैं FROM भाग में सबक्वेरी का उपयोग कर रहा हूं। मुझे बड़ी तालिकाओं से कनेक्ट और क्वेरी की आवश्यकता है, "दास" तालिका में 28 मिलियन रिकॉर्ड है लेकिन परिणाम केवल 128 है इसलिए छोटे परिणाम बड़े डेटा! मैं इस पर MAX () फ़ंक्शन का उपयोग कर रहा हूं।

पहले मैं LEFT JOIN का उपयोग कर रहा हूँ क्योंकि मुझे लगता है कि यह सही तरीका है, mysql आदि को इष्टतम कर सकता है। दूसरी बार सिर्फ परीक्षण के लिए, मैं JOIN के खिलाफ उप-चयन करने के लिए फिर से लिखता हूँ।

बाईं ओर रनटाइम: 1.12s उप-चयन रनटाइम: 0.06s

सम्मिलित होने की तुलना में 18 गुना अधिक तेजी से सबसिलेशन! बस चोकिटो एड में। सबसिले भयानक दिखता है लेकिन परिणाम ...


-1

यदि आप शामिल होकर अपनी क्वेरी को गति देना चाहते हैं:

"इनर जॉइन / जॉइन" के लिए, "ओएन" स्थिति में इसका उपयोग करने के बजाए, जहां शर्त का उपयोग करें। उदाहरण के लिए:

     select id,name from table1 a  
   join table2 b on a.name=b.name
   where id='123'

 Try,

    select id,name from table1 a  
   join table2 b on a.name=b.name and a.id='123'

"लेफ्ट / राइट जॉइन" के लिए, "ऑन" कंडीशन में उपयोग न करें, क्योंकि यदि आप लेफ्ट / राइट जॉइन का उपयोग करते हैं तो इसे किसी एक टेबल के लिए सभी पंक्तियाँ मिलेंगी। इसलिए, "ऑन" में इसका उपयोग करने का कोई फायदा नहीं। तो, "कहाँ" स्थिति का उपयोग करने का प्रयास करें


यह SQL सर्वर और क्वेरी की जटिलता पर निर्भर करता है। बहुत सारे SQL कार्यान्वयन सबसे अच्छे प्रदर्शन के लिए इस तरह के सरल प्रश्नों को अनुकूलित करेंगे। शायद एक उदाहरण सर्वर नाम और संस्करण प्रदान करें जहां उत्तर को बेहतर बनाने के लिए यह व्यवहार होता है?
ट्रेंडफिशर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.