mongooose/mongodb流vs数组性能
当涉及从MongoDB使用Mongoose,Express和JSONStream(如果适用)发送文档集合时,我看到一些意外的性能数字。我想比较猫鼬发现与流。我曾预计更大的文档集合的速度会更快,但很惊讶地发现toArray变体的表现一直超越它们。我在想通配符可能是我使用JSONStream来表达响应。我简单的端点都低于:mongooose/mongodb流vs数组性能
// 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是罪魁祸首,从光标流到表达响应的最佳方式是什么?如果我将它全部缓冲起来,是不是与其中一个数组变种一样?
注意DB服务器是mongo 2.4.x,mongo驱动程序是1.4.x.
更新我只定时读取/流部分而不是序列化方面。阵列变种和流媒体在阵列变体(14.9ms vs. 15.3ms)方面略有优势。下面是端点:
// 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));
});
});
更新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"
}
这将是有益的,看看db.mycollection.stats的输出()和DB .mycollection.find({})。explain()来自mongo shell。
考虑到你所看到的性能数字,对于一个足够大的集合来说,一个非索引查询的冷树可能是所有时间都在的地方,而不是节点本身的任何开销。
感谢您的回复!我用这些命令的输出更新了问题。我想Mongo会很有效地做这个搜索,因为我只是要求它能找到的第一批500个文件 - 没有订单或任何东西。 – Anon 2014-10-19 16:47:57
因此,在任何情况下,这是1000个对象,或约400K的数据,这是在Mongo的噪音领土中。在集合中有1亿个对象时,光标流变得有趣;与你现在在里面有什么关系,要么查询会很快,可能难以区分。 – 2014-10-19 16:53:21