2010-10-16 21 views
42

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

मेरे पास MySQL में डेटाबेस तालिका है जो प्रत्येक दिन के लिए सदस्य प्रोफ़ाइल दृश्यों की संख्या ट्रैक करती है। परीक्षण के लिए इसमें 10,000,000 पंक्तियां हैं।

CREATE TABLE `profile_views` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `username` varchar(20) NOT NULL, 
    `day` date NOT NULL, 
    `views` int(10) unsigned default '0', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `username` (`username`,`day`), 
    KEY `day` (`day`) 
) ENGINE=InnoDB; 

विशिष्ट डेटा ऐसा दिखाई दे सकता है।

+--------+----------+------------+------+ 
| id  | username | day  | hits | 
+--------+----------+------------+------+ 
| 650001 | Joe  | 2010-07-10 | 1 | 
| 650002 | Jane  | 2010-07-10 | 2 | 
| 650003 | Jack  | 2010-07-10 | 3 | 
| 650004 | Jerry | 2010-07-10 | 4 | 
+--------+----------+------------+------+ 

मैं 2010-07-16 के बाद से शीर्ष 5 सबसे ज्यादा देखी गई प्रोफ़ाइल प्राप्त करने के लिए इस क्वेरी का उपयोग करता हूं।

SELECT username, SUM(hits) 
FROM profile_views 
WHERE day > '2010-07-16' 
GROUP BY username 
ORDER BY hits DESC 
LIMIT 5\G 

यह क्वेरी एक मिनट के भीतर पूरा हो जाती है। बुरा नहीं!

अब मोंगोडीबी की दुनिया में आगे बढ़ रहा है। मैं 3 सर्वर का उपयोग कर एक sharded वातावरण सेटअप। सर्वर एम, एस 1, और एस 2। मैंने रिग अप सेट करने के लिए निम्न आदेशों का उपयोग किया (नोट: मैंने आईपी एडिस को अस्पष्ट कर दिया है)।

S1 => 127.20.90.1 
./mongod --fork --shardsvr --port 10000 --dbpath=/data/db --logpath=/data/log 

S2 => 127.20.90.7 
./mongod --fork --shardsvr --port 10000 --dbpath=/data/db --logpath=/data/log 

M => 127.20.4.1 
./mongod --fork --configsvr --dbpath=/data/db --logpath=/data/log 
./mongos --fork --configdb 127.20.4.1 --chunkSize 1 --logpath=/data/slog 

एक बार उन है और चल रहे थे, मैं सर्वर एम पर हॉप, और मोंगो का शुभारंभ किया। मैं निम्न कमांड जारी:

use admin 
db.runCommand({ addshard : "127.20.90.1:10000", name: "M1" }); 
db.runCommand({ addshard : "127.20.90.7:10000", name: "M2" }); 
db.runCommand({ enablesharding : "profiles" }); 
db.runCommand({ shardcollection : "profiles.views", key : {day : 1} }); 
use profiles 
db.views.ensureIndex({ hits: -1 }); 

मैं तो MySQL से ही 10,000,000 पंक्तियों आयातित है, जो मुझे दस्तावेजों है कि इस तरह दिखना दिया:

{ 
    "_id" : ObjectId("4cb8fc285582125055295600"), 
    "username" : "Joe", 
    "day" : "Fri May 21 2010 00:00:00 GMT-0400 (EDT)", 
    "hits" : 16 
} 

अब असली मांस और आलू यहां आता है ... मेरा नक्शा और कार्यों को कम करें। सर्वर एम पर वापस खोल में मैं क्वेरी सेट अप करता हूं और इसे इस तरह निष्पादित करता हूं।

use profiles; 
var start = new Date(2010, 7, 16); 
var map = function() { 
    emit(this.username, this.hits); 
} 
var reduce = function(key, values) { 
    var sum = 0; 
    for(var i in values) sum += values[i]; 
    return sum; 
} 
res = db.views.mapReduce(
    map, 
    reduce, 
    { 
     query : { day: { $gt: start }} 
    } 
); 

और यहाँ मैं समस्याएं आ रहे थे। इस प्रश्न को पूरा करने में 15 मिनट से अधिक समय लगे! MySQL क्वेरी एक मिनट से कम समय ले ली। यहां आउटपुट है:

{ 
     "result" : "tmp.mr.mapreduce_1287207199_6", 
     "shardCounts" : { 
       "127.20.90.7:10000" : { 
         "input" : 4917653, 
         "emit" : 4917653, 
         "output" : 1105648 
       }, 
       "127.20.90.1:10000" : { 
         "input" : 5082347, 
         "emit" : 5082347, 
         "output" : 1150547 
       } 
     }, 
     "counts" : { 
       "emit" : NumberLong(10000000), 
       "input" : NumberLong(10000000), 
       "output" : NumberLong(2256195) 
     }, 
     "ok" : 1, 
     "timeMillis" : 811207, 
     "timing" : { 
       "shards" : 651467, 
       "final" : 159740 
     }, 
} 

न केवल इसे चलाने के लिए हमेशा लिया जाता है, लेकिन परिणाम भी सही नहीं लगते हैं।

db[res.result].find().sort({ hits: -1 }).limit(5); 
{ "_id" : "Joe", "value" : 128 } 
{ "_id" : "Jane", "value" : 2 } 
{ "_id" : "Jerry", "value" : 2 } 
{ "_id" : "Jack", "value" : 2 } 
{ "_id" : "Jessy", "value" : 3 } 

मुझे पता है कि उन मान संख्याओं को बहुत अधिक होना चाहिए।

पूरे MapReduce प्रतिमान की मेरी समझ यह है कि इस क्वेरी को निष्पादित करने का कार्य सभी शर्ड सदस्यों के बीच विभाजित होना चाहिए, जो प्रदर्शन में वृद्धि करनी चाहिए। मैं तब तक इंतजार कर रहा था जब तक आयात के बाद दो शर्ड सर्वरों के बीच दस्तावेजों को वितरित नहीं किया गया। जब मैंने यह प्रश्न शुरू किया तो प्रत्येक के पास लगभग 5,000,000 दस्तावेज़ थे।

तो मुझे कुछ गलत करना होगा। क्या कोई मुझे कोई संकेत दे सकता है?

संपादित करें: आईआरसी पर किसी ने दिन के क्षेत्र में एक सूचकांक जोड़ने का उल्लेख किया है, लेकिन जहां तक ​​मैं बता सकता हूं कि यह मोंगोडीबी द्वारा स्वचालित रूप से किया गया था।

+0

गह .. बस एक कारण का एहसास हुआ कि परिणाम गलत क्यों हैं। मुझे "हिट" के बजाय "मूल्य" पर सॉर्ट करना चाहिए था। – mellowsoon

+2

एक समस्या यह है कि जब आप अपना डेटा मोंगो में आयात करते हैं, तो 'दिन' मान एक विशाल स्ट्रिंग है, लेकिन mysql में, यह एक तिथि (पूर्णांक) है।जब आप अपना डेटा मोंगो में डालते हैं, तो इसे डेट प्रकार के रूप में स्टोर करना सुनिश्चित करें। – Clint

+0

आप दिनांक और समय फ़ील्ड को भी अलग कर सकते हैं, और तिथि को "20110101" या पूर्णांक 20110101 के रूप में संग्रहीत कर सकते हैं और –

उत्तर

53

ओ रेली से MongoDB निश्चित गाइड के अंश:

MapReduce का उपयोग कर की कीमत गति है: समूह विशेष रूप से तेजी से नहीं है, लेकिन MapReduce धीमी है और में इस्तेमाल किया जा नहीं होना चाहिए है " वास्तविक समय। " आप मैड्रिडस को पृष्ठभूमि नौकरी के रूप में चलाते हैं, यह परिणामों का संग्रह बनाता है, और फिर आप उस समय संग्रह क्वेरी कर सकते हैं।

options for map/reduce: 

"keeptemp" : boolean 
If the temporary result collection should be saved when the connection is closed. 

"output" : string 
Name for the output collection. Setting this option implies keeptemp : true. 
+8

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

+6

@mellowsoon, निश्चित रूप से मैप्रिडस का उद्देश्य डेटा की एक बड़ी या बड़ी मात्रा को संसाधित करना है। यह सिर्फ मोंगोडीबी का कार्यान्वयन है जो बहुत तेज़ नहीं है। – TTT

+0

@ टीटीटी - धन्यवाद! अभी मैं सोच रहा हूं कि मोंगोडब अभी भी उस डेटा के प्रकार के लिए सही विकल्प है जिसे हम सहेजने की कोशिश कर रहे हैं, लेकिन ऐसा लगता है कि मुझे डेटा को वास्तव में क्रंच करने के लिए कुछ अन्य मैड्रिडस तकनीकों का उपयोग करना पड़ सकता है। – mellowsoon

6

आप कुछ भी गलत नहीं कर रहे हैं। (गलत मान पर सॉर्ट करने के अलावा जैसा कि आपने पहले ही अपनी टिप्पणियों में देखा है।)

MongoDB मानचित्र/प्रदर्शन को कम करना इतना अच्छा नहीं है। यह एक जाना - माना मुद्दा है; उदाहरण के लिए देखें http://jira.mongodb.org/browse/SERVER-1197 जहां एम/आर से एक निष्क्रिय दृष्टिकोण ~ 350x तेज है।

हालांकि एक फायदा यह है कि आप mapReduce कॉल के out तर्क के साथ एक स्थायी आउटपुट संग्रह नाम निर्दिष्ट कर सकते हैं। एक बार एम/आर पूरा हो जाने के बाद अस्थायी संग्रह का नाम स्थायी रूप से स्थायी नाम पर बदल दिया जाएगा। इस तरह आप अपने आंकड़े अपडेट शेड्यूल कर सकते हैं और एम/आर आउटपुट संग्रह रीयल-टाइम से पूछ सकते हैं।

+0

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

+0

@mellowsoon: उसी तर्क के साथ संग्रह पर गिनती करके अपनी क्वेरी सत्यापित करें (और याद रखें कि जेएस डेट ऑब्जेक्ट का महीना शून्य-आधारित अनुक्रमित है)। –

+0

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

27

शायद मैं बहुत देर हो चुकी

पहले हूँ, लेकिन ..., तुम संग्रह में जानना चाहते हैं एक सूचकांक के बिना MapReduce भरने के लिए। आप "दिन" पर एक सूचकांक बनाते हैं।

MongoDB MapReduce एकल सर्वर पर एकल थ्रेड किया गया है, लेकिन shards पर समानांतर है। मोंगो shards में डेटा sharding कुंजी द्वारा क्रमबद्ध संगत हिस्सों में एक साथ रखा जाता है।

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

डेटा फैलाने के लिए दिन कुंजी के सामने कुछ जोड़ें। उपयोगकर्ता नाम एक अच्छा विकल्प हो सकता है।

इस तरह नक्शा को कम करने के लिए सभी सर्वरों पर लॉन्च किया जाएगा और उम्मीद है कि तीन बार समय कम हो जाएगा।

कुछ इस तरह:

use admin 
db.runCommand({ addshard : "127.20.90.1:10000", name: "M1" }); 
db.runCommand({ addshard : "127.20.90.7:10000", name: "M2" }); 
db.runCommand({ enablesharding : "profiles" }); 
db.runCommand({ shardcollection : "profiles.views", key : {username : 1,day: 1} }); 
use profiles 
db.views.ensureIndex({ hits: -1 }); 
db.views.ensureIndex({ day: -1 }); 

मैं उन परिवर्धन के साथ लगता है, आप MySQL गति, और भी तेज़ी से मिलान कर सकते हैं।

इसके अलावा, बेहतर समय का उपयोग न करें। यदि आपके डेटा को "बारीक" सटीक होने की आवश्यकता नहीं है, तो शेड्यूल नक्शा हर समय कार्य को कम करता है और परिणाम संग्रह का उपयोग करता है।

+1

इसके अलावा, एक आखिरी बात यह है कि मोंगोडीबी आपको यह सुनिश्चित करने के लिए कहता है कि आपकी अनुक्रमणिका स्मृति में रखा जा सकता है; चल रहा db.views.stats() आपको सूचकांक आकार बताता है। यह आपको प्रदर्शन को अनुकूलित और अधिकतम करने में मदद करता है। – Krynble

0

क्या आपने पहले से ही मोंगोडब के लिए हैडूप कनेक्टर का उपयोग करने का प्रयास किया है? इस लिंक यहाँ पर

देखो: http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-hadoop/

आप केवल 3 टुकड़े का उपयोग कर रहे हैं, मैं नहीं जानता कि क्या यह दृष्टिकोण अपने मामले में सुधार होगा।

संबंधित मुद्दे