聚合的内存上限
聚合管道里需要缓存的阶段(如排序、分组、分桶)默认受 100MB 内存上限约束,超限即报错中断。allowDiskUse: true 允许这些阶段把中间结果写到磁盘临时文件继续执行,是让大任务跑完的兜底开关。它解决的是「能不能跑完」,不是「跑得快」——真正的优化仍是减少进入重阶段的文档量。
基本信息
| 默认上限 | 每个需要缓存的阶段 100MB |
|---|---|
| 落盘开关 | db.coll.aggregate(pipeline, { allowDiskUse: true }) |
| 受影响阶段 | $sort、$group、$bucket、$bucketAuto、$lookup、$setWindowFields 等 |
| 其他选项 | maxTimeMS、collation、readConcern、cursor 批次设置 |
| 分片场景 | 在 mongos 上执行时选项会下发到各分片 |
| 服务端默认 | 较新版本支持在实例级设置默认值,具体参数名与版本以手册为准 |
典型使用场景
- 历史数据一次性汇总:任务允许慢但必须跑完,用落盘兜底
- 大范围排序取 Top N:无法减少输入量时先保证能执行
- 报表批处理:离线任务可以接受磁盘 IO 换取成功率
- 排查超限原因:先用 explain 找到内存占用最大的阶段,再决定优化或落盘
- 分片集群聚合:确认选项正确下发,避免部分分片失败
示例
示例
// 允许阻塞阶段落盘,避免 100MB 上限导致任务中断
db.orders.aggregate([
{ $match: { ts: { $gte: ISODate("2026-01-01T00:00:00Z") } } }, // 先收敛输入
{ $project: { sku: 1, qty: 1, _id: 0 } }, // 再瘦身
{ $group: { _id: "$sku", total: { $sum: "$qty" } } },
{ $sort: { total: -1 } },
{ $limit: 100 }
], { allowDiskUse: true, maxTimeMS: 60000 })
// 找体量最大的阶段:看执行计划里各阶段的耗时与中间结果
// db.orders.explain("executionStats").aggregate([...])行为读法
| 现象 | 含义 | 处理方式 |
|---|---|---|
| 报内存超限错误 | 某个阻塞阶段超过上限 | 先减少输入量,其次开启落盘 |
| 开启落盘后仍然很慢 | 磁盘 IO 成为瓶颈 | 优化管道顺序与投影,别把落盘当性能手段 |
| 分片查询部分分片失败 | 选项未覆盖全部执行路径 | 确认在 mongos 执行且选项正确下发 |
| 临时文件占用磁盘 | 落盘期间产生临时数据 | 为磁盘预留空间并监控使用率 |
| 结果顺序与预期不同 | 落盘合并后的输出顺序不保证 | 需要顺序时显式 $sort 并明确排序键 |
落盘是兜底手段:排序与分组的数据量越大磁盘 IO 越重,优先减少进入重阶段的文档量——把 $match 与 $project 前置,往往比打开落盘更有效。
开启落盘会让任务对磁盘可用空间产生依赖:磁盘写满时任务失败并可能影响同实例的其他操作,建议配合磁盘水位告警。