मेरे पास संबंधपरक डेटाबेस के साथ एक लंबा इतिहास है, लेकिन मैं मोंगोडीबी और मैपरेडस के लिए नया हूं, इसलिए मैं लगभग सकारात्मक हूं, मुझे कुछ गलत करना होगा। मैं सवाल में सीधे कूद जाऊंगा। क्षमा करें अगर यह लंबा है।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 दस्तावेज़ थे।
तो मुझे कुछ गलत करना होगा। क्या कोई मुझे कोई संकेत दे सकता है?
संपादित करें: आईआरसी पर किसी ने दिन के क्षेत्र में एक सूचकांक जोड़ने का उल्लेख किया है, लेकिन जहां तक मैं बता सकता हूं कि यह मोंगोडीबी द्वारा स्वचालित रूप से किया गया था।
गह .. बस एक कारण का एहसास हुआ कि परिणाम गलत क्यों हैं। मुझे "हिट" के बजाय "मूल्य" पर सॉर्ट करना चाहिए था। – mellowsoon
एक समस्या यह है कि जब आप अपना डेटा मोंगो में आयात करते हैं, तो 'दिन' मान एक विशाल स्ट्रिंग है, लेकिन mysql में, यह एक तिथि (पूर्णांक) है।जब आप अपना डेटा मोंगो में डालते हैं, तो इसे डेट प्रकार के रूप में स्टोर करना सुनिश्चित करें। – Clint
आप दिनांक और समय फ़ील्ड को भी अलग कर सकते हैं, और तिथि को "20110101" या पूर्णांक 20110101 के रूप में संग्रहीत कर सकते हैं और –