mongodb - MongoDB查询响应太慢
问题描述
我正在开发一个 Golang 项目(db MongoDB)。我已经执行了以下查询,但加载数据需要太多时间。在此,我从具有多个阶段的 2 个集合中获取数据。
db.getCollection('Collection1').aggregate([
{
"$lookup": {
"localField": "uid",
"from": "collection2",
"foreignField": "_id",
"as": "user_info"
}
},
{
"$unwind": "$user_info"
},
{
"$lookup": {
"localField": "cid",
"from": "collection3",
"foreignField": "_id",
"as": "cust_info"
}
},
{
"$lookup": {
"from": "logs",
"let": {"id": "$_id"},
"pipeline": [
{"$match": {"$expr": {"$eq": ["$$id", "$log_id"]}}},
{"$sort": {"log_type": 1}}],
"as": "logs_data"
}
},
{
"$sort": {"logs_data.logged_on":-1}
},
{
"$skip": 1
},
{
"$limit": 2
},
])
我的要求是在同一查询中添加 2 次排序:
- 在日志数组中
"$sort": {"log_type": 1}}
- 对于最终结果
"$sort": {"logs_data.logged_on":-1}
为此,我尝试了以下索引:
{"logged_on" : -1}
{"log_id":1, "log_type":1}
但是查询仍然需要 6-7 秒才能执行。
如果我删除"$sort": {"logs_data.logged_on":-1}
它,它会运行得很快,但是这种排序会花费太多时间。
如何以及我可以做些什么来改善响应时间。
解决方案
该聚合在做什么:
- 从 collection1 中检索所有文档
- 对于 collection1 中的每个文档,在 collection2 中查找单个文档
- 对于 collection1 中的每个文档,在 collection3 中查找单个文档
- 对于 collection1 中的每个文档,在日志中查找所有相关文档
- 对于 collection1 中的每个文档,对从日志中检索到的文档执行内存排序
- 执行内存排序以对文档进行排序
- 保留其中 2 个文件并丢弃其余文件
对于 collection1 中的每个文档,它是 3 次文档提取(加上 #4 中未知的提取次数)、2 次索引扫描和内存排序。
如果 collection1 中有大量的文档,那就是大量的工作,除了 2 个文档之外的所有文档都是浪费的。
如果可以安全地假设其中的每个文档都logs
包含log_id
映射回 的a collection1
,那么您可以:
- 创建一个索引
{logged_on:1, log_id:1}
- 在日志收集上启动聚合
- 排序方式
logged_on: 1
- 项目
{logged_on:1, log_id:1, _id:0}
(这使得聚合的第一部分完全被上述索引覆盖) - 分组
log_id
,$first
取值logged_on
- 排序依据
logged_on: 1
(分组分配排序) - 根据需要跳过和限制
collection1
与当地log_id
外籍人士一起查找_id
- replaceRoot , newRoot 是查找的文档
- 执行您正在使用的现有管道阶段 - 这次他们只会为您要返回的 2 个文档获取/排序。
推荐阅读
- typescript - 强制打字稿查看 (AType = string) !== (BType = string) 之间的区别
- sql - 在 Laravel 中计算两个带有时间戳的日期之间的差异
- ios - 在 SwiftUI 中加载异步请求时显示活动指示器
- python - 在 docker 容器中找不到 Python 模块
- git - git status 时不想看到很少修改的文件
- postgresql - Postgresql 函数表名参数
- c++ - 为什么我已经定义了一个未初始化的局部变量错误?
- wordpress - Wordpress - 外部开发人员添加了这些页面文件夹 - 如何将页面从一个文件夹移动到另一个文件夹?
- r - 是否可以将转换结果存储在 SQL 服务器中的变量(R 脚本/ Power Query 之类)中
- python - 我正在尝试制作一个将 iptables 添加到我的服务器的 python 脚本,但我遇到了一些错误