मैं अन्य उत्तरों की सामान्य धारणा से सहमत हूं कि यह एक सीमा रेखा . है संबंधपरक समस्या।
MongoDB डेटा मॉडल की कुंजी लेखन-भारीपन है, लेकिन यह इस उपयोग के मामले के लिए मुश्किल हो सकता है, ज्यादातर बहीखाता पद्धति के कारण जिसकी आवश्यकता होगी यदि आप उपयोगकर्ताओं को सीधे आइटम से जोड़ना चाहते हैं (एक समूह में परिवर्तन जिसके बाद बहुत सारे हैं उपयोगकर्ताओं की एक बड़ी संख्या में लिखना होगा, और ऐसा करने के लिए आपको कुछ कार्यकर्ता की आवश्यकता होगी)।
आइए जांच करें कि क्या रीड-हैवी मॉडल यहां लागू नहीं है, या क्या हम समयपूर्व अनुकूलन कर रहे हैं।
पढ़ें भारी दृष्टिकोण
आपकी मुख्य चिंता निम्नलिखित उपयोग का मामला है:
<ब्लॉकक्वॉट>
एक वास्तविक प्रदर्शन समस्या तब हो सकती है जब मैं उन सभी समूहों को प्राप्त करना चाहता हूं जिनका उपयोगकर्ता किसी विशिष्ट आइटम के लिए अनुसरण कर रहा है [...] group_id के साथ item_groups $in
और आइटम आईडी।
आइए इसे विच्छेदित करें:
-
उन सभी समूहों को प्राप्त करें जिनका उपयोगकर्ता अनुसरण कर रहा है
यह एक सरल प्रश्न है:
db.followers.find({userId : userId})
. हमेंuserId
. पर एक अनुक्रमणिका की आवश्यकता होगी जो इस ऑपरेशन के रनटाइम को O (लॉग n) बना देगा, या बड़े n के लिए भी तेजी से धधक रहा होगा। -
उसमें से group_id
$in
. के साथ सभी item_groups खोजें और आइटम आईडीअब यह पेचीदा हिस्सा है। आइए एक पल के लिए मान लें कि वस्तुओं के बड़ी संख्या में समूहों का हिस्सा होने की संभावना नहीं है। फिर एक मिश्रित अनुक्रमणिका
{ itemId, groupId }
सबसे अच्छा काम करेगा, क्योंकि हम पहले मानदंड के माध्यम से निर्धारित उम्मीदवार को नाटकीय रूप से कम कर सकते हैं - यदि कोई आइटम केवल 800 समूहों में साझा किया जाता है और उपयोगकर्ता 220 समूहों का अनुसरण कर रहा है, तो मोंगोडब को केवल इनका प्रतिच्छेदन खोजने की आवश्यकता है, जो तुलनात्मक रूप से आसान है क्योंकि दोनों सेट छोटे होते हैं।
हालांकि, हमें इससे अधिक गहराई तक जाना होगा:
आपके डेटा की संरचना शायद है एक जटिल नेटवर्क . का . जटिल नेटवर्क कई स्वादों में आते हैं, लेकिन यह समझ में आता है कि आपका अनुयायी ग्राफ लगभग स्केल-फ्री है, जो कि सबसे खराब स्थिति भी है। एक स्केल फ्री नेटवर्क में, बहुत कम संख्या में नोड्स (सेलिब्रिटीज, सुपर बाउल, विकिपीडिया) बहुत सारे 'ध्यान' को आकर्षित करते हैं (यानी कई कनेक्शन हैं), जबकि बहुत बड़ी संख्या में नोड्स को समान मात्रा में ध्यान आकर्षित करने में परेशानी होती है। संयुक्त ।
छोटे नोड चिंता का कारण नहीं हैं , डेटाबेस की राउंड-ट्रिप सहित उपरोक्त क्वेरी 2ms रेंज . में हैं लाखों कनेक्शन और> 5GB डेटा वाले डेटासेट पर मेरी विकास मशीन पर। अब वह डेटा सेट बहुत बड़ा नहीं है, लेकिन इससे कोई फर्क नहीं पड़ता कि आप कौन सी तकनीक चुनते हैं, रैम बाध्य होगा क्योंकि किसी भी मामले में सूचकांक रैम में होना चाहिए (डेटा इलाके और नेटवर्क में पृथक्करण आम तौर पर खराब है), और सेट चौराहे का आकार है परिभाषा के अनुसार छोटा। दूसरे शब्दों में:इस व्यवस्था में हार्डवेयर बाधाओं का बोलबाला है।
सुपरनोड्स . के बारे में क्या हालांकि?
चूंकि यह अनुमान होगा और मुझे नेटवर्क मॉडल में बहुत दिलचस्पी है, इसलिए मैंने कुछ माप करने के लिए आपके डेटा मॉडल के आधार पर नाटकीय रूप से सरलीकृत नेटवर्क टूल को लागू करने की स्वतंत्रता ली। (क्षमा करें, यह C# में है, लेकिन अच्छी तरह से संरचित नेटवर्क बनाना उस भाषा में काफी कठिन है जिसमें मैं सबसे अधिक धाराप्रवाह हूं...)।
सुपरनोड्स की क्वेरी करते समय, मुझे 7ms टॉप . की श्रेणी में परिणाम मिलते हैं (यह 1.3GB डीबी में 12M प्रविष्टियों पर है, जिसमें इसमें 133,000 आइटम वाले सबसे बड़े समूह हैं और एक उपयोगकर्ता जो 143 समूहों का अनुसरण करता है।)
धारणा इस कोड में यह है कि उपयोगकर्ता द्वारा अनुसरण किए जाने वाले समूहों की संख्या बहुत बड़ी नहीं है, लेकिन यह यहां उचित लगता है। यदि ऐसा नहीं है, तो मैं लेखन-भारी दृष्टिकोण अपनाऊंगा।
कोड के साथ खेलने के लिए स्वतंत्र महसूस करें। दुर्भाग्य से, यदि आप इसे कुछ जीबी से अधिक डेटा के साथ आज़माना चाहते हैं, तो इसे थोड़ा अनुकूलन की आवश्यकता होगी, क्योंकि यह केवल अनुकूलित नहीं है और यहां और वहां कुछ बहुत ही अक्षम गणना करता है (विशेष रूप से बीटा-भारित यादृच्छिक फेरबदल में सुधार किया जा सकता है) )।
दूसरे शब्दों में:मैं अभी तक रीड-हैवी दृष्टिकोण के प्रदर्शन के बारे में चिंता नहीं करता . समस्या अक्सर इतनी नहीं होती है कि उपयोगकर्ताओं की संख्या बढ़ती है, लेकिन उपयोगकर्ता अप्रत्याशित तरीके से सिस्टम का उपयोग करते हैं।
द राइट हेवी अप्रोच
वैकल्पिक तरीका शायद लिंक करने के क्रम को उलट देना है:
UserItemLinker
{
userId,
itemId,
groupIds[] // for faster retrieval of the linker. It's unlikely that this grows large
}
यह शायद सबसे अधिक स्केलेबल डेटा मॉडल है, लेकिन मैं इसके लिए तब तक नहीं जाऊंगा जब तक कि हम बड़ी मात्रा में डेटा के बारे में बात नहीं कर रहे हैं जहां शार्डिंग एक महत्वपूर्ण आवश्यकता है। यहाँ मुख्य अंतर यह है कि अब हम शार्प की के हिस्से के रूप में userId का उपयोग करके डेटा को कुशलतापूर्वक विभाजित कर सकते हैं। यह बहु-डेटासेंटर-परिदृश्यों में क्वेरीज़ को समानांतर बनाने, कुशलतापूर्वक शार्प करने और डेटा स्थान को बेहतर बनाने में मदद करता है।
इसका परीक्षण टेस्टबेड के अधिक विस्तृत संस्करण के साथ किया जा सकता है, लेकिन मुझे अभी तक समय नहीं मिला, और स्पष्ट रूप से, मुझे लगता है कि यह अधिकांश अनुप्रयोगों के लिए अधिक है।