MongoDB 聚合管道性能优化的八条军规

Raj Kumar | 2026-08-26T23:00:55 | Database

总结 MongoDB Aggregation Pipeline 中 match 前置、索引覆盖、allowDiskUse 等八条关键优化规则。

# MongoDB 聚合管道性能优化的八条军规 ## 军规一:$match 和 $sort 尽量前置 ```javascript // 好:先过滤再分组 db.orders.aggregate([ { $match: { status: "completed", createdAt: { $gte: ISODate("2024-01-01") } } }, { $group: { _id: "$userId", total: { $sum: "$amount" } } }, { $sort: { total: -1 } }, { $limit: 10 } ]); // 差:先分组再过滤(全表扫描) db.orders.aggregate([ { $group: { _id: "$userId", total: { $sum: "$amount" } } }, { $match: { total: { $gt: 1000 } } } ]); ``` ## 军规二:利用索引 `$match` 和 `$sort` 放在管道开头时可以利用索引。确保字段有复合索引。 ```javascript db.orders.createIndex({ status: 1, createdAt: -1 }); ``` ## 军规三:$project 减少传递字段 ```javascript { $project: { userId: 1, amount: 1, _id: 0 } } ``` 减少后续阶段的数据传输量。 ## 军规四:$lookup 优化 ```javascript // 使用 pipeline 形式的 $lookup,可以在子查询中过滤 { $lookup: { from: "users", let: { uid: "$userId" }, pipeline: [ { $match: { $expr: { $eq: ["$_id", "$uid"] } } }, { $project: { name: 1, _id: 0 } } ], as: "user" } } ``` ## 军规五:allowDiskUse 当聚合超过 100MB 内存限制时使用: ```javascript db.orders.aggregate([...], { allowDiskUse: true }); ``` ## 军规六:避免 $unwind 后再 $group 尽量用 `$addToSet`、`$push` 直接在 `$group` 中处理数组。 ## 军规七:使用 $facet 并行执行 ```javascript { $facet: { totalCount: [{ $count: "count" }], data: [{ $skip: 0 }, { $limit: 10 }] } } ``` ## 军规八:善用 explain ```javascript db.orders.explain("executionStats").aggregate([...]); ``` 检查 `totalDocsExamined` 和 `executionTimeMillis`,确保没有意外的全表扫描。

← Back to Blog