Mongodb 了解explain()以优化复杂查询
我有一个聚合管道,需要5秒钟才能返回200行。 我正试图使用explain(“executionStats”)优化我当前的管道 这是我的管道:Mongodb 了解explain()以优化复杂查询,mongodb,indexing,lookup,explain,Mongodb,Indexing,Lookup,Explain,我有一个聚合管道,需要5秒钟才能返回200行。 我正试图使用explain(“executionStats”)优化我当前的管道 这是我的管道: db.getCollection("content_topics").explain("executionStats").aggregate([{ "$lookup": { from: "users", localField: "creator", foreignField: "_id", as:
db.getCollection("content_topics").explain("executionStats").aggregate([{
"$lookup": {
from: "users",
localField: "creator",
foreignField: "_id",
as: "user"
}
},
{
$unwind: "$user"
},
{
"$match": {
created_at: {
"$gte": 1528914600,
"$lte": 1534271400
},
dash_status: 3,
language: "hi",
parent_topic_id: {
"$eq": null
},
status: 1,
"user.device_os": {
"$ne": "BOT"
}
}
},
{
"$sort": {
created_at: -1
}
},
{
"$addFields": {
user_handle: "$user.handle",
user_phone: "$user.phone",
user_status: "$user.status"
}
},
{
"$project": {
topic_id: 1,
n_vokes: 1,
message: 1,
title: 1,
language: 1,
description: 1,
voice_desc: 1,
image: 1,
image_share: 1,
hashtag: 1,
location: 1,
default_text: 1,
creator: 1,
created_at: 1,
status: 1,
ref_id: 1,
weightage: 1,
username: 1,
slug_generated: 1,
user_handle: 1,
user_phone: 1,
user_status: 1
}
},
{
"$skip": 0
},
{
"$limit": 200
}
]);
这就是mongo解释的内容:
这是在我使用“$match”中使用的键创建了索引“index\u for_dashboard”之后。我还从用户集合中为“device_os”创建了一个索引。但是没有骰子,响应时间没有改善
可能的罪犯:
- 美元很贵。如果是,我可以只取我需要的字段
- 索引可以做得更好吗。我应该使用另一套吗 田地
- addField美元贵吗。如果是的话,我可以把它卸到 应用程序级别
我不能在这里打电话,需要一些指导。首先,您需要确保至少运行MongoDB的v3.6.3,因为在v3.6中有一个新功能,允许指定子管道。这些管道实际上可以使用索引,但是,只有在上面提到的版本中才修复了一个问题 以下内容应尽可能快:
db.getCollection("content_topics").createIndex({ created_at: -1, dash_status: 1, language: 1, parent_topic_id: 1, status: 1 }); // this index will get used by the main $match and the $sort stage
db.getCollection("users").createIndex({ device_os: 1 }); // this index will get used by the sub-pipeline in $lookup
db.getCollection("content_topics").aggregate([{
"$match": { // filter at the start in order to be able to use indexes
created_at: {
"$gte": 1528914600,
"$lte": 1534271400
},
dash_status: 3,
language: "hi",
parent_topic_id: {
"$eq": null
},
status: 1
// see the below $lookup stage in case you're wondering where the user filter went
}
},
{
"$sort": {
created_at: -1 // sort straight away so the index can be used
}
},
{
"$lookup": {
from: "users",
let: { "creator": "$creator" },
pipeline: [{ // use new v3.6 pipeline syntax to be able to leverage indexes
$match: {
$expr: {
$and: [
{ $eq: [ "$_id", "$$creator" ] },
{ $ne: [ "$device_os", "BOT" ] } // here is the "device_os" filter inside the pipeline so index can be used
]
}
}
}, {
$project: {
_id: 0, // "_id" field is not needed
user_handle: 1, // only those fields are of interest
user_phone: 1,
user_status: 1
}
}],
as: "user"
}
},
{
$unwind: "$user"
},
{
"$project": {
topic_id: 1,
n_vokes: 1,
message: 1,
title: 1,
language: 1,
description: 1,
voice_desc: 1,
image: 1,
image_share: 1,
hashtag: 1,
location: 1,
default_text: 1,
creator: 1,
created_at: 1,
status: 1,
ref_id: 1,
weightage: 1,
username: 1,
slug_generated: 1,
user_handle: "$user.handle", // no extra $addFields stage needed
user_phone: "$user.phone", // same here
user_status: "$user.status" // and here
}
},
{
"$skip": 0
},
{
"$limit": 200
}
]);
首先,您需要确保至少运行MongoDB的v3.6.3,因为在v3.6中有一个新特性,允许指定子管道。这些管道实际上可以使用索引,但是,只有在上面提到的版本中才修复了一个问题 以下内容应尽可能快:
db.getCollection("content_topics").createIndex({ created_at: -1, dash_status: 1, language: 1, parent_topic_id: 1, status: 1 }); // this index will get used by the main $match and the $sort stage
db.getCollection("users").createIndex({ device_os: 1 }); // this index will get used by the sub-pipeline in $lookup
db.getCollection("content_topics").aggregate([{
"$match": { // filter at the start in order to be able to use indexes
created_at: {
"$gte": 1528914600,
"$lte": 1534271400
},
dash_status: 3,
language: "hi",
parent_topic_id: {
"$eq": null
},
status: 1
// see the below $lookup stage in case you're wondering where the user filter went
}
},
{
"$sort": {
created_at: -1 // sort straight away so the index can be used
}
},
{
"$lookup": {
from: "users",
let: { "creator": "$creator" },
pipeline: [{ // use new v3.6 pipeline syntax to be able to leverage indexes
$match: {
$expr: {
$and: [
{ $eq: [ "$_id", "$$creator" ] },
{ $ne: [ "$device_os", "BOT" ] } // here is the "device_os" filter inside the pipeline so index can be used
]
}
}
}, {
$project: {
_id: 0, // "_id" field is not needed
user_handle: 1, // only those fields are of interest
user_phone: 1,
user_status: 1
}
}],
as: "user"
}
},
{
$unwind: "$user"
},
{
"$project": {
topic_id: 1,
n_vokes: 1,
message: 1,
title: 1,
language: 1,
description: 1,
voice_desc: 1,
image: 1,
image_share: 1,
hashtag: 1,
location: 1,
default_text: 1,
creator: 1,
created_at: 1,
status: 1,
ref_id: 1,
weightage: 1,
username: 1,
slug_generated: 1,
user_handle: "$user.handle", // no extra $addFields stage needed
user_phone: "$user.phone", // same here
user_status: "$user.status" // and here
}
},
{
"$skip": 0
},
{
"$limit": 200
}
]);
感谢您花时间详细解释这一点。我完全不知道我们可以在$lookup中使用管道,这非常漂亮,可以让我在查找之前放置匹配项。此外,它还有助于缩短响应时间,这可以通过
nReturned
/works
将响应时间从7k降低到2k来确认:感谢您花时间详细解释这一点。我完全不知道我们可以在$lookup中使用管道,这非常漂亮,可以让我在查找之前放置匹配项。此外,它还有助于缩短响应时间,这可以通过nReturned
/works
将响应时间从7k降低到2k来确认: