क्या तेज़ है, एक बड़ी क्वेरी या कई छोटे प्रश्न?


68

मैं विभिन्न कंपनियों के लिए काम कर रहा हूं, और मैंने देखा है कि उनमें से कुछ ऐसे विचार रखना पसंद करते हैं जो अपने सभी "रिश्तेदारों" के साथ एक तालिका में शामिल होंगे। लेकिन फिर कुछ बार आवेदन पर, हमें केवल 1 कॉलम का उपयोग करना होगा।

तो क्या यह सिंपल सिलेक्ट करने के लिए तेज़ होगा, और फिर सिस्टम कोड पर उन्हें "जॉइन" करना होगा?

सिस्टम php, java, asp, किसी भी भाषा जो डेटाबेस से कनेक्ट हो सकता है।

तो सवाल यह है कि क्या तेजी से सर्वर साइड (php, java, asp, ruby, python ...) से डेटाबेस में एक क्वेरी चलती है जो हमें चाहिए या सर्वर साइड से डेटाबेस तक जा रही है और एक रन उस समय केवल एक तालिका से कॉलम प्राप्त करें?


2
आप 'एसक्यूएल' के किस कार्यान्वयन का उपयोग कर रहे हैं? MySQL, Microsoft SQL Server, Oracle, Postgresql, आदि? कृपया अपना टैग अपडेट करें।
आरएलएफ


6
मेरा अनुभव यह है कि MySQL जटिल प्रश्नों को पसंद नहीं करता है और आमतौर पर बहुत ही सामान्य प्रश्नों (लेकिन अधिक) के साथ तेज़ होता है। पोस्टग्रैज का क्वेरी ऑप्टिमाइज़र बहुत बेहतर है और एक बड़ी क्वेरी को चलाने के लिए आमतौर पर अधिक कुशल है।
a_horse_with_no_name 12

3
@a_horse_with_no_name यह बहुत व्यापक सामान्यीकरण है, विशेष रूप से इस प्रश्न के संदर्भ में। MySQL ऑप्टिमाइज़र वास्तव में डिज़ाइन द्वारा बहुत सरल है, और MySQL के पुराने संस्करणों पर-जुड़ाव और उप-प्रश्नों के साथ-साथ समस्याओं का कारण बन सकता है- अन्यथा PostgreSQL में तेजी से योजनाओं का उत्पादन होता है, जबकि MySQL शुद्ध OLTP भार के लिए बहुत तेज़ हो सकता है। हालांकि, प्रश्न के संदर्भ में, एक बड़ी क्वेरी तेजी से होगी, मान लीजिए कि संभवत: सबसे खराब संभावित परिदृश्य- प्रोग्रामिंग लूप के अंदर का चयन (कोई फर्क नहीं पड़ता RDBMS का इस्तेमाल किया गया)।
जीनस

2
@jynus: ठीक है, सवाल है बहुत व्यापक (प्लस: मैं ने कहा, "मेरे अनुभव में" - अन्य लोगों को अलग-अलग अनुभव हो सकता है)। LOOP के अंदर एक क्वेरी कभी भी एक अच्छा विचार नहीं है और लगभग हमेशा खराब डिज़ाइन या समझने की कमी का परिणाम है कि रिलेशनल डेटाबेस के साथ कैसे काम किया जाए।
a_horse_with_no_name

जवाबों:


68

आपका प्रश्न क्या संबोधित करेगा विषय JOIN DECOMPOSITION है।

पुस्तक के पृष्ठ २० ९ के अनुसार

उच्च प्रदर्शन MySQL

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

SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';

आप इन प्रश्नों को चला सकते हैं:

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

पृथ्वी पर आप ऐसा क्यों करेंगे? यह पहली नज़र में बेकार लगता है, क्योंकि आपने बदले में कुछ भी प्राप्त किए बिना प्रश्नों की संख्या बढ़ा दी है। हालांकि, इस तरह के पुनर्गठन वास्तव में महत्वपूर्ण प्रदर्शन लाभ दे सकते हैं:

  • कैशिंग अधिक कुशल हो सकता है। कई एप्लिकेशन "ऑब्जेक्ट" को कैश करते हैं जो सीधे टेबल पर मैप करते हैं। इस उदाहरण में, यदि टैग के साथ ऑब्जेक्ट mysqlपहले से ही कैश है, तो एप्लिकेशन पहले क्वेरी को छोड़ देगा। यदि आपको कैश में 123, 567, या 908 की आईडी के साथ पोस्ट मिलते हैं, तो आप उन्हें IN()सूची से हटा सकते हैं । क्वेरी कैश भी इस रणनीति से लाभान्वित हो सकता है। यदि तालिकाओं में से केवल एक बार बदलता है, तो एक जोड़ को विघटित करने से कैश अमान्य की संख्या कम हो सकती है।
  • व्यक्तिगत रूप से प्रश्नों को निष्पादित करना कभी-कभी लॉक विवाद को कम कर सकता है
  • एप्लिकेशन में जुड़ने से विभिन्न सर्वरों पर टेबल रखकर डेटाबेस को स्केल करना आसान हो जाता है।
  • प्रश्न स्वयं अधिक कुशल हो सकते हैं। इस उदाहरण में, IN()शामिल होने के बजाय एक सूची का उपयोग करने से MySQL को पंक्ति IDs सॉर्ट करने में मदद मिलती है और एक पंक्ति के साथ संभव से अधिक पंक्तियों को पुनः प्राप्त किया जा सकता है।
  • आप निरर्थक पंक्ति एक्सेस को कम कर सकते हैं। एप्लिकेशन में शामिल होने का अर्थ है प्रत्येक पंक्ति को केवल एक बार पुनर्प्राप्त करना। जबकि क्वेरी में शामिल होना अनिवार्य रूप से एक अपभ्रंश है जो बार-बार एक ही डेटा तक पहुंच सकता है। इसी कारण से, इस तरह के पुनर्गठन से कुल नेटवर्क ट्रैफ़िक और मेमोरी उपयोग भी कम हो सकता है।
  • कुछ हद तक, आप इस तकनीक को देख सकते हैं क्योंकि नेस्टेड लूप्स एल्गोरिथ्म MySQL के बजाय मैन्युअल रूप से हैश को कार्यान्वित करने के लिए एक शामिल होने के लिए उपयोग करता है। एक हैश ज्वाइन अधिक कुशल हो सकता है।

नतीजतन, जब आप कैश करते हैं और पहले के प्रश्नों से बहुत सारे डेटा का पुन: उपयोग करते हैं, तो आप एप्लिकेशन में do ज़्यादा जुड़ सकते हैं, आप कई सर्वरों पर डेटा वितरित करते हैं, आप IN()जॉइन को सूचियों से प्रतिस्थापित करते हैं, या एक जुड़ाव कई बार उसी तालिका को संदर्भित करता है।

अवलोकन

मुझे पहला बुलेटपॉइंट पसंद है क्योंकि जब यह क्वेरी कैश को क्रॉसचेक करता है तो InnoDB थोड़ा भारी-भरकम होता है।

अंतिम बुलेटपॉइंट के लिए, मैंने 11 मार्च, 2013 को एक पोस्ट वापस लिखा था ( क्या एक JOIN स्थिति और WHERE की स्थिति के बीच एक निष्पादन अंतर है? ) नेस्टेड लूप एल्गोरिथ्म का वर्णन करता है। इसे पढ़ने के बाद, आप देखेंगे कि कितना अच्छा विघटन हो सकता है।

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

कुछ प्रदर्शन से संतुष्ट हो सकते हैं और कोड को नहीं छू सकते हैं। यदि वे रचना में शामिल होने का प्रयास करते हैं तो अन्य को यह एहसास नहीं होता कि महान लाभ हो सकते हैं।

उन डेवलपर्स के लिए जो तैयार हैं ...

कोशिश करो !!!


3
3 प्रश्नों को बदलने के बारे में उस लिंक के लिए ... मुझे पता है और बैरन, वादिम और पीटर का सम्मान करते हैं, लेकिन मैं इस भ्रामक सुझाव से असहमत हूं। विभाजन के पक्ष में अधिकांश तर्क इतने दुर्लभ हैं कि उल्लेख के लायक नहीं हैं। JOINs के साथ एक ही क्वेरी से चिपके रहें, फिर इसे सुधारने पर काम करें।
रिक जेम्स

2
@RickJames मैं आपकी टिप्पणी की भावना से सहमत हूं। वर्षों से, मैंने कुछ के लिए अपघटन कार्य में शामिल होने और दूसरों के लिए असफल होने को देखा है। यदि उचित अपघटन सही नहीं किया जाता है, तो भी उचित एसक्यूएल कौशल के साथ, यह आपके खिलाफ काम कर सकता है। मेरे वर्तमान नियोक्ता में, कई डिपो को स्केलिंग से प्यार है, खासकर जब विरासत कोड शामिल है और गहरी जेबें उपलब्ध हैं। उन लोगों के साथ जिनके पास कैवियार स्वाद है, लेकिन अंडे का सलाद बजट, अपघटन में शामिल होने के जोखिम के लायक हो सकता है, लेकिन सही किया जाना चाहिए।
RolandoMySQLDBA

मुझे यह देखने में अच्छा लगेगा कि यदि मेरे पास अधिकार और समय हो तो यह Oracle वातावरण में कैसे काम करता है।
रिक हेंडरसन

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

24

में Postgres (और शायद इसी तरह की एक सीमा तक किसी भी आरडीबीएमएस, MySQL कुछ हद तक), कम प्रश्नों लगभग हमेशा से रहे हैं बहुत तेजी से।

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

क्लाइंट में किए जाने वाले अतिरिक्त काम के बारे में नहीं, परिणामों के संयोजन के बारे में, जो आमतौर पर बहुत धीमा है। एक RDBMS उस तरह के कार्य में माहिर है और संचालन मूल डेटा प्रकारों पर आधारित है। textमध्यवर्ती परिणामों के लिए या ग्राहक के मूल प्रकारों में बदलने के लिए कोई कास्टिंग नहीं है , जिससे कम सही (या गलत) परिणाम भी हो सकते हैं। फ्लोटिंग पॉइंट नंबरों के बारे में सोचें ...

आप DB सर्वर और क्लाइंट के बीच अधिक डेटा भी ट्रांसफर करते हैं। मूल्यों से भरे हाथ के लिए यह नगण्य हो सकता है, या बहुत बड़ा अंतर हो सकता है।

यदि एकाधिक क्वेरीज़ का मतलब डेटाबेस सर्वर के लिए कई राउंड ट्रिप है, तो आप नेटवर्क लेटेंसी और ट्रांजेक्शन ओवरहेड को भी कई बार इकट्ठा करते हैं, संभवतः कनेक्शन ओवरहेड भी। बड़ा, बड़ा नुकसान।

आपके सेटअप के आधार पर, नेटवर्क लेटेंसी अकेले परिमाण के आदेशों द्वारा बाकी सभी की तुलना में अधिक समय ले सकती है।

SO पर संबंधित प्रश्न:

बहुत बड़े , लंबे चलने वाले प्रश्नों के लिए एक महत्वपूर्ण मोड़ हो सकता है क्योंकि लेनदेन रास्ते में DB पंक्तियों पर ताले एकत्र करते हैं। बहुत बड़े प्रश्नों में विस्तारित अवधि के लिए कई ताले हो सकते हैं जिससे समवर्ती प्रश्नों के साथ घर्षण हो सकता है ।


जिज्ञासा से बाहर, आप बहुत बड़ा क्या मानते हैं ?
सेबलफॉस्ट

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

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

1
@ जस्टामार्टिन: आरडीबीएमएस के क्वेरी प्लानर द्वारा संभाले गए क्वेरी के प्रकार की तरह लगता है - सही प्रश्नों को मानते हुए। के बारे में returns lots of redundant data for "parent" table: आप बेमानी डेटा क्यों लौटाएंगे? केवल आपको आवश्यक डेटा वापस करें।
इरविन ब्रान्डेसटेटर

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