javascript - 使用 Node.js 的 MongoDB 聚合性能问题
问题描述
我有一些关于 MongoDB 聚合性能的问题。
我的数据库有 43'000'000 个文档,当我尝试调用后端时它从不响应(我确定问题出在数据库中,使用较少的文档集一切正常)。
我实际上使用的是 Node.js,它是 Mongoose 模块。
这是模型的样本
var PingSchema = new Schema({
provider: String,
from_zone: String,
to_zone: String,
from_host: String,
to_host: String,
icmp_seq: Number,
ttl: Number,
time: Number,
timestamp: { type : Date, default: Date.now }
}).plugin(mongoosePaginate);
const Ping = mongoose.model('Ping', PingSchema);
我正在使用 Express 创建一些路由,这是来自后端的两个主要查询的代码
router.route('/pings/query/avgOfEveryPingOfSelectedDate').get(async (req, res, next) => {
var start, end, sameRegion;
start = new Date(req.query.start + "T00:00:00-00:00");
end = new Date(req.query.end + "T23:59:59-00:00");
sameRegion = parseInt(req.query.sameRegion);
Ping.aggregate()
.project({sameRegion: {$cmp: ['$from_zone', '$to_zone']}, provider: "$provider", time: "$time", timestamp: "$timestamp"})
.match({$and: [{sameRegion: sameRegion}, {timestamp: {$gte: start, $lte: end}}]})
.group({_id : "$provider", avg: { $avg: "$time" }, count: { $sum: 1 }})
.exec(function (err, resp) {
if (err) {
// TODO
console.log(err);
} else {
res.json(resp);
}
})
});
router.route('/pings/query/avgOfEveryDayOfSelectedYear').get(async (req, res, next) => {
var year, provider, sameRegion;
year = parseInt(req.query.year);
provider = req.query.provider;
sameRegion = parseInt(req.query.sameRegion);
Ping.aggregate()
.project({sameRegion: {$cmp: ['$from_zone', '$to_zone']}, provider: "$provider", time: "$time", timestamp: "$timestamp", "year": {"$year":"$timestamp"}, "dayOfYear": { "$dayOfYear": "$timestamp" }})
.match({$and: [{sameRegion: sameRegion}, {year: year}, {provider: provider}]})
.group({_id : {"provider": "$provider", "dayOfYear": "$dayOfYear"}, avg: { $avg: "$time" }, count: { $sum: 1 }})
.sort({"_id": 1})
.exec(function (err, resp) {
if (err) {
// TODO
console.log(err);
} else {
res.json(resp);
}
})
});
第一个查询输入两个日期并返回此范围内所有 ping 的平均时间。第二个需要一年和一个选定的提供者(一个简单的字符串),并返回所有匹配条件的 ping 的平均值。
我在问我的代码是否错误(或者它需要一些优化)或者我是否应该做一些缓存或并行化的事情(也许 MongoDB 有一些关于这方面的功能?)。
提前感谢大家。
编辑1:也许 allowDiskOption 或某些索引有用?
编辑2:我已经在提供程序和时间戳上实现了 allowDiskOption 和一些索引,但查询仍然很慢。问题就在这里:这些查询在这个大数据集上太慢了。
// By day in month
db.pings.aggregate(
[
{$project: {month: {"$month":"$timestamp"}}},
{$match: {$and: [{provider: "AWS"},{month:8}]}},
{$group:{_id: {"$dayOfYear":"$timestamp"}, avg: {$avg:"$time"}}},
{$sort:{_id:1}}
],
{
allowDiskUse: true
}
)
// In two dates
db.pings.aggregate(
[
{$match:{timestamp:{$gte:ISODate("2018-08-10T00:00:00.0Z"), $lte:ISODate("2018-08-18T23:59:59.0Z")}}},
{$group:{_id: "$provider", avg: {$avg:"$time"}}}
],
{
allowDiskUse: true
}
)
我现在要问的是:如何优化这些查询?
再次感谢
解决方案
推荐阅读
- asterisk - 如何获取来电显示变量?
- java - 一个 LDAP 的 AD 身份验证失败,但另一个 LDAP 通过
- pyinstaller - 在可执行文件中运行 Xgboost 时出现问题
- kotlin - 如何使用 kotlin 作为服务器端语言?
- sql - 将使用 switch case 创建的 SQL 视图转换为 Postgresql
- python - 从 SPSS 到 Python 日期的整数日期
- peg - 是否可以以先行方式使用链接规则引用?
- ansible - 如何使用 ansible-playbook 将文件和文件夹复制到远程机器上的另一个文件夹?
- asp.net - 命名空间“PagedList”中不存在类型或命名空间名称“MVC”-VS 2019,MVC 5.2.7
- c++ - Qt 程序无故意外结束