我正在使用3 node Mongo cluster
运行10GB RAM
(版本3.0有线老虎存储引擎)。
我有2 million
个文档,每个文档都有25 - 30 fields
,其中2个是基本数组。
我正在执行aggregation
150 -170 milliseconds
的查询。
当我生成100 queries/sec
的负载时,性能开始降低,最多可达2秒。
db.testCollection.aggregate( [
{ $match: { vid: { $in: ["001","002"]} , ss :"N" , spt : { $gte : new Date("2016-06-29")}, spf :{ $lte : new Date("2016-06-27")}}},
{ $match: {$or : [{sc:{$elemMatch :{$eq : "TEST"}}},{sc :{$exists : false}}]}},
{ $match: {$or : [{pt:{$ne : "RATE"}},{rpis :{$exists : true}}]}},
{ $project: { vid: 1, pid: 1, pn: 1, pt: 1, spf: 1, spt: 1, bw: 1, bwe: 1, st: 1, et: 1, ls: 1, dw: 1, at: 1, dt: 1, d1: 1, d2: 1, mldv: 1, aog: 1, nn: 1, mn: 1, rpis: 1, lmp: 1, cid: 1, van: 1, vad: 1, efo: 1, sc: 1, ss: 1, m: 1, pr: 1, obw: 1, osc: 1, m2: 1, crp: 1, sce: 1, dce: 1, cns: 1 }},
{ $group: { _id: null , data: { $push: "$$ROOT" } }
},
{ $project: { _id: 1 , data : 1 } }
]
)
所有字段都有一个复合索引,顺序与查询的顺序相同("rpis"
除外,因为复合索引只能有一个数组字段)。
请在我出错的地方建议。
答案 0 :(得分:1)
最后两个阶段是不必要的。
最后一组是非常重的,因为它在内存中创建了新数组,但是你的结果应该在这个阶段由应用程序消化(不使用组)。
并且可能有一个绿灯可以删除之前的$project
,因为可能更便宜将完整文档推送到客户端 - 这可能值得一试。
当第一次使用$match
时 - 然后使用索引,第二次和第三次匹配与第一个管道的结果集一起使用而不是使用创建的索引的风险很大。如果您有办法尝试压缩$match
阶段只有一个,并查看查询的执行方式。
以下简化版本的查询:
db.testCollection.aggregate([{
$match : {
vid : {
$in : ["001", "002"]
},
ss : "N",
spt : {
$gte : new Date("2016-06-29")
},
spf : {
$lte : new Date("2016-06-27")
}
}
}, {
$match : {
$or : [{
sc : {
$elemMatch : {
$eq : "TEST"
}
}
}, {
sc : {
$exists : false
}
}
]
}
}, {
$match : {
$or : [{
pt : {
$ne : "RATE"
}
}, {
rpis : {
$exists : true
}
}
]
}
}])
其他问题可能是影响将系统扩展到分片环境的业务规则 - 在开始使用此类文档结构之前,您是否估算了负载?