क्या व्यक्तिगत प्रश्न जुड़ने से ज्यादा तेज हैं?


44

वैचारिक प्रश्न: क्या व्यक्तिगत प्रश्न जुड़ने की तुलना में तेज हैं, या: क्या मुझे ग्राहक की ओर से वांछित प्रत्येक जानकारी को एक सेलेक्ट स्टेटमेंट में निचोड़ने की कोशिश करनी चाहिए या केवल उतना ही उपयोग करना चाहिए जितना सुविधाजनक लगता है?

टीएल; डीआर : अगर मेरी क्वेरी व्यक्तिगत प्रश्नों को चलाने में अधिक समय लेती है, तो क्या यह मेरी गलती है या यह उम्मीद की जानी चाहिए?

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

मैंने एक अत्यंत सरल उदाहरण को एक साथ रखने की कोशिश की है:

एसक्यूएल फिडल

स्कीमा सेटअप :

CREATE TABLE MASTER 
( ID INT NOT NULL
, NAME VARCHAR2(42 CHAR) NOT NULL
, CONSTRAINT PK_MASTER PRIMARY KEY (ID)
);

CREATE TABLE DATA
( ID INT NOT NULL
, MASTER_ID INT NOT NULL
, VALUE NUMBER
, CONSTRAINT PK_DATA PRIMARY KEY (ID)
, CONSTRAINT FK_DATA_MASTER FOREIGN KEY (MASTER_ID) REFERENCES MASTER (ID)
);

INSERT INTO MASTER values (1, 'One');
INSERT INTO MASTER values (2, 'Two');
INSERT INTO MASTER values (3, 'Three');

CREATE SEQUENCE SEQ_DATA_ID;

INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 1, 1.3);
INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 1, 1.5);
INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 1, 1.7);
INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 2, 2.3);
INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 3, 3.14);
INSERT INTO DATA values (SEQ_DATA_ID.NEXTVAL, 3, 3.7);

क्वेरी A :

select NAME from MASTER
where ID = 1

परिणाम :

| NAME |
--------
|  One |

क्वेरी B :

select ID, VALUE from DATA
where MASTER_ID = 1

परिणाम :

| ID | VALUE |
--------------
|  1 |   1.3 |
|  2 |   1.5 |
|  3 |   1.7 |

क्वेरी C :

select M.NAME, D.ID, D.VALUE 
from MASTER M INNER JOIN DATA D ON M.ID=D.MASTER_ID
where M.ID = 1

परिणाम :

| NAME | ID | VALUE |
---------------------
|  One |  1 |   1.3 |
|  One |  2 |   1.5 |
|  One |  3 |   1.7 |

बेशक, मैंने इनमें से किसी भी प्रदर्शन को नहीं मापा, लेकिन कोई भी निरीक्षण कर सकता है:

  • क्वेरी A + B क्वेरी सी के रूप में उपयोग करने योग्य जानकारी की एक ही राशि लौटाता है।
  • A + B को क्लाइंट को 1 + 2x3 == 7 "डेटा सेल" वापस करना होगा
  • C को क्लाइंट को 3x3 == 9 "डेटा सेल्स" वापस करना होगा, क्योंकि जॉइन के साथ मैं स्वाभाविक रूप से परिणाम सेट में कुछ अतिरेक शामिल करता हूं।

इससे सामान्यीकरण (जहाँ तक यह है):

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

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


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
जैक डगलस

1
मैंने एक बेंचमार्क चलाया और परिणामों को मीडियम पर एक लेख में पोस्ट किया । मैंने यहाँ एक उत्तर जोड़ा होगा, लेकिन पहले से ही यह एक और प्रश्न पर था , और एक ही उत्तर को कई प्रश्नों पर पोस्ट करना गलत है
बेंजामिन

जवाबों:


45

क्या व्यक्तिगत प्रश्न जुड़ने की तुलना में तेज़ होते हैं, या: क्या मुझे ग्राहक की ओर से इच्छित प्रत्येक जानकारी को एक सेलेक्ट स्टेटमेंट में निचोड़ने का प्रयास करना चाहिए या केवल उतना ही उपयोग करना चाहिए जितना सुविधाजनक लगता है?

किसी भी प्रदर्शन परिदृश्य में, आपको यह देखने के लिए समाधानों का परीक्षण और माप करना होगा कि कौन सा तेज़ है

उस ने कहा, यह लगभग हमेशा मामला है कि एक ठीक से ट्यून किए गए डेटाबेस से सेट किया गया रिजल्ट क्लाइंट के लिए स्रोत पंक्तियों को वापस करने और फिर उन्हें वहां शामिल करने से बेहतर होगा। विशेष रूप से, यदि इनपुट सेट बड़े हैं और परिणाम सेट छोटा है - दोनों रणनीतियों के संदर्भ में निम्नलिखित क्वेरी के बारे में सोचें: दो पंक्तियों को एक साथ मिलाएं जो 100 पंक्तियों के परिणाम के साथ 5 जीबी प्रत्येक हैं। यह एक चरम है, लेकिन आप मेरी बात देखिए।

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

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

एक ज्वाइन की गई क्वेरी को हमेशा अलग-अलग प्रश्नों की तुलना में अधिक डेटा वापस करना होता है जो समान जानकारी प्राप्त करते हैं।

आमतौर पर ऐसा नहीं है। अधिकांश समय भले ही इनपुट सेट बड़े हों, परिणाम सेट इनपुट के योग से बहुत छोटा होगा।

अनुप्रयोग के आधार पर, क्लाइंट को लौटाए जा रहे बहुत बड़े क्वेरी परिणाम सेट तत्काल लाल ध्वज होते हैं: क्लाइंट डेटा के इतने बड़े सेट के साथ क्या कर रहा है जो डेटाबेस के करीब नहीं किया जा सकता है? किसी उपयोगकर्ता को 1,000,000 पंक्तियों को प्रदर्शित करना कम से कम कहने के लिए अत्यधिक संदिग्ध है। नेटवर्क बैंडविड्थ भी एक सीमित संसाधन है।

चूंकि डेटाबेस को डेटा को एक साथ मिलाना होता है, बड़े डेटासेट के लिए कोई यह मान सकता है कि डेटाबेस को व्यक्तिगत की तुलना में एकल सम्मिलित क्वेरी पर अधिक काम करना होगा, क्योंकि (कम से कम) इसके लिए क्लाइंट को अधिक डेटा वापस करना होगा।

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

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

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

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

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


नेटवर्क बैंडविड्थ के लिए +1 भी एक सीमित संसाधन है।
हरि हरकर

ओपी कह रहा है कि जोइनड डेटा परिणाम सेट हमेशा बड़े होते हैं। > एक सम्मिलित क्वेरी को हमेशा अलग-अलग प्रश्नों की तुलना में अधिक डेटा वापस करना होता है। मुझे लगता है कि यह उद्देश्यपूर्ण रूप से सही है (> के लिए), उदाहरण के लिए परिणाम सेट आकार में भिन्न होते हैं, इसलिए तार पर अधिक डेटा। क्या आपके पास एक उदाहरण है जहां यह सच नहीं है? अगर मैं लेखकों में शामिल हो जाऊं -> पोस्ट्स और ऑथर्स में "जीवनी" नामक एक फ़ील्ड है, जो 100 एमबी के लेखक के लिए 1 एमबी JSON फ़ील्ड है, तार पर मैं 100 एमबी बनाम 1 एमबी प्रसारित करूँगा। क्या यह गलत है?
हिटरो

6

बेशक, मैंने इनमें से किसी भी प्रदर्शन को नहीं मापा

आपने कुछ अच्छे नमूना कोड एक साथ रखे। क्या आपने SQL Fiddle में समय को देखा? यहां तक ​​कि कुछ संक्षिप्त अवैज्ञानिक प्रदर्शन परीक्षण से पता चलता है कि आपके प्रदर्शन में क्वेरी तीन को एक या दो अलग-अलग क्वेरी के रूप में चलाने के लिए लगभग एक ही समय लगता है। संयुक्त एक और दो के बारे में दो बार के रूप में लंबे समय के रूप में तीन और किसी भी ग्राहक पक्ष में शामिल होने से पहले किया जाता है।

जैसे-जैसे आप डेटा बढ़ाते हैं, क्वेरी एक और दो की गति अलग हो जाएगी, लेकिन डेटाबेस जॉइन अभी भी तेज होगा।

आपको यह भी विचार करना चाहिए कि अगर आंतरिक जुड़ाव डेटा को खत्म कर रहा है तो क्या होगा।


2

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

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

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


-3

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

अंत में, आप जो अनुभव करते हैं वह कुछ ऐसे हैं जो कई डेवलपर्स देखते हैं। DBAs हमेशा कहते हैं "नहीं, ज्वाइन करें" लेकिन वास्तविकता यह है कि इस मामले में कई सरल चयन करना तेजी से है।


5
इसमें शामिल होने में कोई "नेटवर्क अक्षमता" नहीं है - यह सब डेटाबेस सर्वर पर होता है, इसलिए इसमें कोई नेटवर्क शामिल नहीं है (जब तक कि आप एक डीबी लिंक पर शामिल नहीं हो रहे हैं!)
क्रिस सैक्सन

2
आप विचार कर सकते हैं कि नेटवर्क लेयर में कम्प्रेशन है या नहीं। ओरेकल का SQL * नेट करता है, उसी मान में उसी कॉलम में दोहराते हुए कुशलतापूर्वक संपीड़ित किया जाता है।
डेविड एल्ड्रिज

3
@TomTom में आपके पास एक बिंदु हो सकता है या नहीं (जैसा कि डेविड एल्ड्रिज अंक, संपीड़न मामले), लेकिन आपका शब्दांकन भ्रामक है। "ज्वाइन की नेटवर्क अक्षमता" ? वास्तव में, इसे ठीक करें ताकि यह स्पष्ट हो कि आपका क्या मतलब है।
ypercube y

@ChrisSaxon सुनिश्चित करें कि आपके पास एक रिपोर्ट "शीर्षक-> आधार-> तालिका-पंक्तियों" के लिए तालिकाएं हैं और आपको सभी पंक्तियों की आवश्यकता है ताकि आप इन 3 तालिकाओं में शामिल हों। प्रत्येक तालिका में लंबे संस्करण होते हैं इसलिए जो होता है वह प्रत्येक पंक्ति के लिए होता है जिसे आप इन लंबे संस्करणों को दोहरा रहे हैं। एप्लिकेशन परत को इन सभी स्ट्रिंग्स के लिए मेमोरी आवंटित करने और फिर उन्हें अपने मॉडल के लिए समूहित करने की आवश्यकता है। इसलिए मुझे लगता है कि उसका यही मतलब है, वहाँ अधिक डेटा भेजा गया है
MIKE

@ माइक जो आपके द्वारा चुने गए भावों पर निर्भर करता है, जुड़ने पर नहीं। और नेटवर्क संपीड़न हो सकता है। ओरेकल डाटाबेस एसक्यूएल * में नेट दोहराए गए डुप्लिकेट मानों को हटा देता है nicetheory.io/2018/01/11/…
क्रिस सैक्सन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.