जब आप MongoDB के साथ एप्लिकेशन विकसित कर रहे हों तो उत्कृष्ट डेटाबेस प्रदर्शन महत्वपूर्ण है। कभी-कभी समग्र डेटा प्रस्तुति प्रक्रिया कई कारणों से खराब हो सकती है, जिनमें से कुछ में शामिल हैं:
- अनुचित स्कीमा डिज़ाइन पैटर्न
- अनुक्रमण रणनीतियों का अनुचित उपयोग या उपयोग नहीं करना
- अपर्याप्त हार्डवेयर
- प्रतिकृति अंतराल
- खराब प्रदर्शन करने वाली क्वेरी तकनीक
इनमें से कुछ झटके आपको हार्डवेयर संसाधनों को बढ़ाने के लिए मजबूर कर सकते हैं जबकि अन्य नहीं कर सकते हैं। उदाहरण के लिए, खराब क्वेरी संरचनाओं के परिणामस्वरूप क्वेरी को संसाधित होने में लंबा समय लग सकता है, जिससे प्रतिकृति अंतराल हो सकता है और शायद कुछ डेटा हानि भी हो सकती है। इस मामले में, कोई सोच सकता है कि शायद स्टोरेज मेमोरी पर्याप्त नहीं है, और शायद इसे स्केलिंग की आवश्यकता है। यह लेख आपके MongoDB डेटाबेस के प्रदर्शन को बढ़ावा देने के लिए आपके द्वारा नियोजित सबसे उपयुक्त प्रक्रियाओं पर चर्चा करता है।
स्कीमा डिज़ाइन
मूल रूप से दो सबसे अधिक नियोजित स्कीमा संबंध हैं...
- एक से कुछ
- एक से अनेक
जबकि सबसे कुशल स्कीमा डिज़ाइन एक-से-अनेक संबंध है, प्रत्येक की अपनी खूबियाँ और सीमाएँ हैं।
एक से कुछ
इस मामले में, किसी दिए गए फ़ील्ड के लिए, एम्बेडेड दस्तावेज़ होते हैं लेकिन उन्हें ऑब्जेक्ट पहचान के साथ अनुक्रमित नहीं किया जाता है।
यहाँ एक सरल उदाहरण है:
{
userName: "Brian Henry",
Email : "[email protected]",
grades: [
{subject: ‘Mathematics’, grade: ‘A’},
{subject: English, grade: ‘B’},
]
}
इस संबंध का उपयोग करने का एक लाभ यह है कि आप केवल एक प्रश्न के साथ एम्बेडेड दस्तावेज़ प्राप्त कर सकते हैं। हालाँकि, एक क्वेरी के दृष्टिकोण से, आप एक एम्बेडेड दस्तावेज़ तक नहीं पहुँच सकते। इसलिए यदि आप एम्बेडेड दस्तावेज़ों को अलग से संदर्भित नहीं करने जा रहे हैं, तो इस स्कीमा डिज़ाइन का उपयोग करना इष्टतम होगा।
एक से कई
इस संबंध के लिए एक डेटाबेस में डेटा एक अलग डेटाबेस में डेटा से संबंधित है। उदाहरण के लिए, आपके पास उपयोगकर्ताओं के लिए एक डेटाबेस हो सकता है और दूसरा पोस्ट के लिए। इसलिए यदि कोई उपयोगकर्ता कोई पोस्ट करता है तो उसे उपयोगकर्ता आईडी के साथ रिकॉर्ड किया जाता है।
उपयोगकर्ता स्कीमा
{
Full_name: “John Doh”,
User_id: 1518787459607.0
}
पोस्ट स्कीमा
{
"_id" : ObjectId("5aa136f0789cf124388c1955"),
"postTime" : "16:13",
"postDate" : "8/3/2018",
"postOwnerNames" : "John Doh",
"postOwner" : 1518787459607.0,
"postId" : "1520514800139"
}
इस स्कीमा डिजाइन के साथ लाभ यह है कि दस्तावेजों को स्टैंडअलोन माना जाता है (अलग से चुना जा सकता है)। एक और फायदा यह है कि यह डिज़ाइन विभिन्न आईडी के उपयोगकर्ताओं को पोस्ट स्कीमा (इसलिए नाम वन-टू-मैनी) से जानकारी साझा करने में सक्षम बनाता है और कभी-कभी "एन-टू-एन" स्कीमा हो सकता है - मूल रूप से टेबल जॉइन का उपयोग किए बिना। इस स्कीमा डिज़ाइन के साथ सीमा यह है कि दूसरे संग्रह में डेटा लाने या चुनने के लिए आपको कम से कम दो प्रश्न करने होंगे।
इसलिए डेटा को कैसे मॉडल किया जाए यह एप्लिकेशन के एक्सेस पैटर्न पर निर्भर करेगा। इसके अलावा आपको उस स्कीमा डिज़ाइन पर विचार करने की आवश्यकता है जिसकी हमने ऊपर चर्चा की है।
स्कीमा डिजाइन के लिए अनुकूलन तकनीक
-
जितना संभव हो सके दस्तावेज़ एम्बेडिंग को नियोजित करें क्योंकि यह डेटा के एक विशेष सेट के लिए आपके द्वारा चलाए जाने वाले प्रश्नों की संख्या को कम करता है।
-
अक्सर अद्यतन किए जाने वाले दस्तावेज़ों के लिए असामान्यकरण का उपयोग न करें। यदि एनफील्ड को बार-बार अद्यतन किया जा रहा है, तो उन सभी उदाहरणों को खोजने का कार्य होगा जिन्हें अद्यतन करने की आवश्यकता है। इसके परिणामस्वरूप धीमी क्वेरी प्रोसेसिंग होगी, इसलिए डीनॉर्मलाइजेशन से जुड़े गुण भी भारी पड़ जाएंगे।
-
यदि किसी दस्तावेज़ को अलग से लाने की आवश्यकता है, तो एम्बेडिंग का उपयोग करने की कोई आवश्यकता नहीं है क्योंकि समग्र पाइपलाइनिंग जैसे जटिल प्रश्नों को निष्पादित करने में अधिक समय लगता है।
-
यदि एम्बेड किए जाने वाले दस्तावेज़ों की सरणी काफी बड़ी है, तो उन्हें एम्बेड न करें। सरणी वृद्धि की कम से कम एक सीमित सीमा होनी चाहिए।
उचित अनुक्रमण
यह प्रदर्शन ट्यूनिंग का अधिक महत्वपूर्ण हिस्सा है और इसके लिए आवेदन प्रश्नों पर व्यापक समझ, लिखने के लिए पढ़ने का अनुपात, और आपके सिस्टम की कितनी मुफ्त मेमोरी की आवश्यकता होती है। यदि आप किसी अनुक्रमणिका का उपयोग करते हैं, तो क्वेरी अनुक्रमणिका को स्कैन करेगी न कि संग्रह को।
एक उत्कृष्ट अनुक्रमणिका वह है जिसमें किसी क्वेरी द्वारा स्कैन किए गए सभी फ़ील्ड शामिल होते हैं। इसे कंपाउंड इंडेक्स कहा जाता है।
किसी फ़ील्ड के लिए एकल अनुक्रमणिका बनाने के लिए आप इस कोड का उपयोग कर सकते हैं:
db.collection.createIndex({“fields”: 1})
कंपाउंड इंडेक्स के लिए, इंडेक्सिंग बनाने के लिए:
db.collection.createIndex({“filed1”: 1, “field2”: 1})
इंडेक्सिंग के उपयोग से तेजी से क्वेरी करने के अलावा, अन्य ऑपरेशन जैसे सॉर्ट, सैंपल और लिमिट का एक अतिरिक्त लाभ है। उदाहरण के लिए, यदि मैं अपनी स्कीमा को {f:1, m:1} के रूप में डिज़ाइन करता हूं, तो मैं इस रूप में खोजने के अलावा एक अतिरिक्त ऑपरेशन कर सकता हूं
db.collection.find( {f: 1} ).sort( {m: 1} )
रैम से डेटा पढ़ना डिस्क से समान डेटा को पढ़ने की तुलना में अधिक कुशल है। इस कारण से, हमेशा यह सुनिश्चित करने की सलाह दी जाती है कि आपका इंडेक्स पूरी तरह से रैम में फिट हो। अपने संग्रह का वर्तमान अनुक्रमणिका आकार प्राप्त करने के लिए, कमांड चलाएँ:
db.collection.totalIndexSize()
आपको 36864 बाइट्स जैसा मान मिलेगा। यह मान भी समग्र RAM आकार का एक बड़ा प्रतिशत नहीं लेना चाहिए, क्योंकि आपको सर्वर के पूरे कार्यशील सेट की जरूरतों को पूरा करने की आवश्यकता है।
एक कुशल क्वेरी को चयनात्मकता भी बढ़ानी चाहिए। अनुक्रमणिका का उपयोग करके परिणाम को सीमित करने के लिए एक क्वेरी की क्षमता के रूप में चयनात्मकता को परिभाषित किया जा सकता है। अधिक सुरक्षित होने के लिए, आपके प्रश्नों को अनुक्रमित फ़ील्ड के साथ संभावित दस्तावेज़ों की संख्या को सीमित करना चाहिए। चयनात्मकता ज्यादातर एक यौगिक सूचकांक से जुड़ी होती है जिसमें एक कम-चयनात्मकता क्षेत्र और एक अन्य क्षेत्र शामिल होता है। उदाहरण के लिए यदि आपके पास यह डेटा है:
{ _id: ObjectId(), a: 6, b: "no", c: 45 }
{ _id: ObjectId(), a: 7, b: "gh", c: 28 }
{ _id: ObjectId(), a: 7, b: "cd", c: 58 }
{ _id: ObjectId(), a: 8, b: "kt", c: 33 }
क्वेरी {a:7, b:"cd"} 2 दस्तावेज़ों को स्कैन करके 1 मिलान दस्तावेज़ लौटाएगी। हालाँकि यदि मान a के लिए डेटा समान रूप से वितरित किया जाता है अर्थात
{ _id: ObjectId(), a: 6, b: "no", c: 45 }
{ _id: ObjectId(), a: 7, b: "gh", c: 28 }
{ _id: ObjectId(), a: 8, b: "cd", c: 58 }
{ _id: ObjectId(), a: 9, b: "kt", c: 33 }
क्वेरी {ए:7, बी:"सीडी"} 1 दस्तावेज़ के माध्यम से स्कैन करेगी और इस दस्तावेज़ को वापस कर देगी। इसलिए इसमें पहली डेटा संरचना की तुलना में कम समय लगेगा।
आपके संपूर्ण डेटाबेस इन्फ्रास्ट्रक्चर के लिए ClusterControlSingle कंसोल पता करें कि ClusterControl में और क्या नया है, ClusterControl को निःशुल्क स्थापित करेंसंसाधन प्रावधान
अपर्याप्त स्टोरेज मेमोरी, रैम और अन्य ऑपरेटिंग पैरामीटर मोंगोडीबी के प्रदर्शन को काफी कम कर सकते हैं। उदाहरण के लिए, यदि उपयोगकर्ता कनेक्शन की संख्या बहुत बड़ी है, तो यह सर्वर एप्लिकेशन की समयबद्ध तरीके से अनुरोधों को संभालने की क्षमता में बाधा उत्पन्न करेगा। जैसा कि MongoDB में मॉनिटर करने के लिए प्रमुख चीजों में चर्चा की गई है, आप एक सिंहावलोकन प्राप्त कर सकते हैं कि आपके पास कौन से सीमित संसाधन हैं और आप उन्हें अपने विनिर्देशों के अनुरूप कैसे बढ़ा सकते हैं। बड़ी संख्या में समवर्ती आवेदन अनुरोधों के लिए, डेटाबेस सिस्टम मांग को पूरा करने के लिए अभिभूत होगा।
प्रतिकृति अंतराल
कभी-कभी आप अपने डेटाबेस से कुछ डेटा गायब होते हुए देख सकते हैं या जब आप कुछ हटाते हैं, तो यह फिर से दिखाई देता है। जितना आप अच्छी तरह से डिज़ाइन किया गया स्कीमा, उपयुक्त अनुक्रमण और पर्याप्त संसाधन प्राप्त कर सकते थे, शुरुआत में आपका आवेदन बिना किसी हिचकी के सुचारू रूप से चलेगा लेकिन फिर किसी बिंदु पर आप बाद में उल्लिखित समस्याओं को देखते हैं। MongoDB प्रतिकृति अवधारणा पर निर्भर करता है जहां कुछ डिज़ाइन मानदंडों को पूरा करने के लिए डेटा को अनावश्यक रूप से कॉपी किया जाता है। इसके साथ एक धारणा यह है कि प्रक्रिया तात्कालिक है। हालाँकि, नेटवर्क विफलता या अनहेल्ड त्रुटियों के कारण कुछ विलंब हो सकता है। संक्षेप में, उस समय के बीच एक बड़ा अंतर होगा जिसके साथ प्राथमिक नोड पर एक ऑपरेशन संसाधित किया जाता है और उस समय को द्वितीयक नोड में लागू किया जाएगा।
प्रतिकृति अंतराल के साथ झटके
-
असंगत डेटा। यह विशेष रूप से रीड ऑपरेशंस से जुड़ा है जो सेकेंडरी में वितरित किया जाता है।
-
यदि लैग गैप पर्याप्त चौड़ा है, तो प्राथमिक नोड पर ढेर सारा अनरिप्लिकेटेड डेटा हो सकता है और इसे सेकेंडरी नोड में समेटने की आवश्यकता होगी। कुछ बिंदु पर, यह असंभव हो सकता है, खासकर जब प्राथमिक नोड को पुनर्प्राप्त नहीं किया जा सकता है।
-
प्राथमिक नोड को पुनर्प्राप्त करने में विफलता किसी को डेटा के साथ नोड चलाने के लिए मजबूर कर सकती है जो अद्यतित नहीं है और परिणामस्वरूप प्राथमिक को पुनर्प्राप्त करने के लिए पूरे डेटाबेस को छोड़ सकता है।
द्वितीयक नोड विफलता के कारण
-
CPU, डिस्क IOPS और नेटवर्क I/O विनिर्देशों के संबंध में द्वितीयक पर प्राथमिक शक्ति का मिलान करना।
-
जटिल लेखन संचालन। उदाहरण के लिए एक कमांड जैसे
db.collection.update( { a: 7} , {$set: {m: 4} }, {multi: true} )
प्राथमिक नोड इस ऑपरेशन को ओप्लॉग में काफी तेजी से रिकॉर्ड करेगा। हालांकि, सेकेंडरी नोड के लिए, इसे उन ऑप्स को लाना होगा, रैम में किसी भी इंडेक्स और डेटा पेज को पढ़ना होगा ताकि आईडी जैसे कुछ मानदंड विनिर्देशों को पूरा किया जा सके। चूंकि प्राथमिक नोड के साथ दर को बनाए रखने के लिए इसे इतनी जल्दी करना पड़ता है, ऑपरेशन करता है, अगर ऑप्स की संख्या काफी बड़ी है तो अपेक्षित अंतराल होगा।
-
बैकअप बनाते समय सेकेंडरी को लॉक करना। इस मामले में हम प्राथमिक को अक्षम करना भूल सकते हैं इसलिए इसके संचालन को सामान्य रूप से जारी रखेंगे। उस समय जब लॉक जारी किया जाएगा, विशेष रूप से डेटा बैकअप की एक बड़ी मात्रा से निपटने के दौरान प्रतिकृति अंतराल एक बड़ा अंतर होगा।
-
सूचकांक निर्माण। यदि द्वितीयक नोड में एक इंडेक्स बनता है, तो इससे जुड़े अन्य सभी ऑपरेशन ब्लॉक हो जाते हैं। यदि सूचकांक लंबे समय से चल रहा है तो प्रतिकृति अंतराल हिचकी का सामना करना पड़ेगा।
-
असंबद्ध माध्यमिक। कभी-कभी नेटवर्क डिस्कनेक्शन के कारण सेकेंडरी नोड विफल हो सकता है और इसके परिणामस्वरूप पुन:कनेक्ट होने पर प्रतिकृति लैग हो जाता है।
प्रतिकृति अंतराल को कैसे कम करें
-
_id फ़ील्ड वाले अपने संग्रह के अलावा अद्वितीय अनुक्रमणिका का उपयोग करें। यह प्रतिकृति प्रक्रिया को पूरी तरह विफल होने से बचाने के लिए है।
-
अन्य प्रकार के बैकअप पर विचार करें जैसे पॉइंट-इन-टाइम और फाइल सिस्टम स्नैपशॉट जिन्हें लॉक करने की आवश्यकता नहीं है।
-
बड़े इंडेक्स बनाने से बचें क्योंकि वे बैकग्राउंड ब्लॉकिंग ऑपरेशन का कारण बनते हैं।
-
माध्यमिक को पर्याप्त शक्तिशाली बनाएं। यदि लेखन कार्य हल्का है, तो कम शक्ति वाली सेकेंडरी का उपयोग करना किफायती होगा। लेकिन, भारी लेखन भार के लिए, द्वितीयक नोड प्राथमिक से पीछे रह सकता है। अधिक सेकेंट होने के लिए, सेकेंडरी के पास पर्याप्त बैंडविड्थ होनी चाहिए ताकि ओप्लॉग को इतनी तेज़ी से पढ़ने में मदद मिल सके कि प्राथमिक नोड के साथ इसकी दर बनी रहे।
कुशल क्वेरी तकनीक
अनुक्रमित क्वेरी बनाने और क्वेरी चयनात्मकता का उपयोग करने के अलावा, जैसा कि ऊपर चर्चा की गई है, ऐसी अन्य अवधारणाएं हैं जिनका उपयोग आप अपने प्रश्नों को प्रभावी बनाने के लिए कर सकते हैं।
अपनी क्वेरी को ऑप्टिमाइज़ करना
-
एक कवर क्वेरी का उपयोग करना। एक कवर की गई क्वेरी वह है जो हमेशा एक इंडेक्स द्वारा पूरी तरह से संतुष्ट होती है इसलिए किसी दस्तावेज़ की जांच करने की आवश्यकता नहीं होती है। इसलिए कवर की गई क्वेरी में सभी फ़ील्ड इंडेक्स के हिस्से के रूप में होने चाहिए और परिणामस्वरूप परिणाम में ये सभी फ़ील्ड शामिल होने चाहिए।
आइए इस उदाहरण पर विचार करें:
{_id: 1, product: { price: 50 }
अगर हम इस संग्रह के लिए
. के रूप में एक अनुक्रमणिका बनाते हैं{“product.price”: 1}
एक खोज ऑपरेशन को ध्यान में रखते हुए, यह अनुक्रमणिका इस क्वेरी को कवर करेगी;
db.collection.find( {“product.price”: 50}, {“product.price”: 1, _id: 0} )
और उत्पाद लौटाएं। मूल्य फ़ील्ड और केवल मूल्य।
-
एम्बेडेड दस्तावेज़ों के लिए, डॉट नोटेशन (.) का उपयोग करें। डॉट नोटेशन एक सरणी के तत्वों और एम्बेडेड दस्तावेज़ के क्षेत्रों तक पहुँचने में मदद करता है।
किसी सरणी तक पहुंचना:
{ prices: [12, 40, 100, 50, 40] }
उदाहरण के लिए चौथा तत्व निर्दिष्ट करने के लिए, आप यह आदेश लिख सकते हैं:
“prices.3”
ऑब्जेक्ट ऐरे को एक्सेस करना:
{ vehicles: [{name: toyota, quantity: 50}, {name: bmw, quantity: 100}, {name: subaru, quantity: 300} }
व्हीकल एरे में नाम फ़ील्ड निर्दिष्ट करने के लिए आप इस कमांड का उपयोग कर सकते हैं
“vehicles.name”
-
जांचें कि क्या कोई प्रश्न कवर किया गया है। ऐसा करने के लिए db.collection.explain() का उपयोग करें। यह फ़ंक्शन अन्य कार्यों के निष्पादन के बारे में जानकारी प्रदान करेगा - उदा। db.Collection.explain ()। कुल ()। व्याख्या फ़ंक्शन के बारे में अधिक जानने के लिए आप व्याख्या () देख सकते हैं।
सामान्य तौर पर, जहां तक पूछताछ का संबंध है, सर्वोच्च तकनीक अनुक्रमणिका का उपयोग कर रही है। इंडेक्स के बाहर के दस्तावेज़ों को क्वेरी करने की तुलना में केवल एक इंडेक्स को क्वेरी करना बहुत तेज़ है। वे मेमोरी में फिट हो सकते हैं इसलिए डिस्क के बजाय रैम में उपलब्ध हैं। यह उन्हें स्मृति से लाने में आसान और तेज़ बनाता है।