2014-10-19 3 views
1

Я вижу некоторые неожиданные номера производительности, когда дело доходит до отправки коллекции документов из MongoDB с использованием Mongoose, Express и JSONStream, когда это применимо. Я хотел сравнить поиск мангуста против потока. Я ожидал, что поток будет быстрее для больших коллекций документов, но был удивлен, увидев, что варианты toArray превосходят их последовательно. Я думаю, что подстановочный знак может быть моим использованием JSONStream, чтобы передать ответ, чтобы выразить. Мои простые конечные точки ниже:mongooose/mongodb streams vs array performance

// run this after connecting to mongoose 

var app = express(); 

var myModel = ...; // get mongoose model 
var myCollection = myModel.collection; 

// fetch 500 - use lean w/ mongoose 
var queryOpts = { lean : true, limit : 500 }; 

// 35.958 
app.get("/api/v1/stream", function(req, res) { 
    res.set('Content-Type', 'application/json'); 
    myModel.find({ }, null, queryOpts) 
    .stream().pipe(JSONStream.stringify()).pipe(res); 
}); 

// 36.228 
app.get("/api/v1/mongostream", function(req, res) { 
    res.set('Content-Type', 'application/json'); 
    myCollection.find({ }, queryOpts) 
    .stream().pipe(JSONStream.stringify()).pipe(res); 
}); 

// 23.399ms 
app.get("/api/v1/mongoarray", function(req, res) { 
    myCollection.find({ }, queryOpts) 
    .toArray(function(err, results) { 
     res.json(results); 
    }); 
}); 

// 23.908 
app.get("/api/v1/array", function(req, res) { 
    myModel.find({ }, null, queryOpts, function(err, results) { 
     res.json(results); 
    }); 
}); 

app.listen(4000); 

Комментарий над каждой конечной точки указывает среднее время запроса сообщенный ab -k -n 1000 <endpoint>. Я удивлен, что передача потока курсора в JSONStream для экспресс-ответа примерно на 50% медленнее, чем просто выборка всего и отправка. Я ожидал, что данные будут работать лучше.

Есть ли что-то, что я делаю, это, очевидно, неправильно? Неужели я ошибаюсь, чтобы думать, что потоки должны быть быстрее? Если JSONStream является виновником, то лучший способ перейти от потока курсора к выражению ответа - если я все-таки буду его буферировать, не будет ли это то же самое, что и один из вариантов массива?

Обратите внимание, что сервер БД - это mongo 2.4.x, а драйвер mongo - 1.4.x.

Обновление Я рассчитал только часть выборки/потоковой передачи, а не аспект сериализации. Оба варианта массива и потоковая передача были одинаковыми по времени с небольшим краем к вариантам массива (14,9 мс против 15,3 мс). Ниже приведены конечные точки:

// No serialization - just timing 
// all are nearly the same - slight edge to 
// arrays 
app.get("/api/v2/stream", function(req, res) { 
    var start = process.hrtime(); 
    res.set('Content-Type', 'application/json'); 
    myModel.find({ }, null, queryOpts) 
    .stream().on('end', function() { 
     res.json(process.hrtime(start)); 
    }); 
}); 

app.get("/api/v2/mongostream", function(req, res) { 
    var start = process.hrtime(); 
    res.set('Content-Type', 'application/json'); 
    myCollection.find({ }, queryOpts) 
    .stream().on('end', function() { 
     res.json(process.hrtime(start)); 
    }); 
}); 

app.get("/api/v2/mongoarray", function(req, res) { 
    var start = process.hrtime(); 
    myCollection.find({ }, queryOpts) 
    .toArray(function(err, results) { 
     res.json(process.hrtime(start)); 
    }); 
}); 

app.get("/api/v2/array", function(req, res) { 
    var start = process.hrtime(); 
    myModel.find({ }, null, queryOpts, function(err, results) { 
     res.json(process.hrtime(start)); 
    }); 
}); 

Update 2 Выход collection.stats() и collection.find({}).explain() ниже:

> db.myCollection.stats(); 
{ 
    "ns" : "myDb.myCollection", 
    "count" : 1000, 
    "size" : 419264, 
    "avgObjSize" : 419.264, 
    "storageSize" : 847872, 
    "numExtents" : 4, 
    "nindexes" : 2, 
    "lastExtentSize" : 655360, 
    "paddingFactor" : 1, 
    "systemFlags" : 1, 
    "userFlags" : 0, 
    "totalIndexSize" : 98112, 
    "indexSizes" : { 
     "_id_" : 40880, 
     "_meta.tags_1" : 57232 
    }, 
    "ok" : 1 
} 
> db.myCollection.find({}).explain(); 
{ 
    "cursor" : "BasicCursor", 
    "isMultiKey" : false, 
    "n" : 1000, 
    "nscannedObjects" : 1000, 
    "nscanned" : 1000, 
    "nscannedObjectsAllPlans" : 1000, 
    "nscannedAllPlans" : 1000, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 0, 
    "indexBounds" : { 

    }, 
    "server" : "LOCAL:27017" 
} 
+1

Таким образом, в любом случае это 1000 объектов или около 400 тыс. Данных, что является своего рода территорией шума для Монго. С 100 миллионами объектов в коллекции поток курсора становится интересным; с тем, что у вас есть сейчас, либо запрос будет быстрым, вероятно, неразличимым. –

ответ

0

Было бы полезно, чтобы увидеть выход db.mycollection.stats() и БД .mycollection.find ({}). explain() из оболочки монго.

Учитывая, что номера производительности вы видите, может быть просто, что для достаточно большой коллекции холодный удар btree для неиндексированного запроса - это время, куда все время идет, а не на какие-либо издержки в узле как таковое ,

+0

Спасибо за ответ! Я обновил вопрос с выводами этих команд. Я подумал, что Монго будет делать находку действительно эффективно, так как я просто прошу первых 500 документов, которые он может найти - ни ордера, ни чего-либо еще. – Anon