首页/数据/NoSQL 速查/allowDiskUse 与聚合内存限制
MongoDB99 条

allowDiskUse 与聚合内存限制

聚合各阶段默认内存上限 100MB:超限报错时显式传 allowDiskUse:true 让阶段落盘,或先重构管道降低中间结果体积。

NoSQL 速查数据更新于 2026-10-13

聚合的内存上限

聚合管道里需要缓存的阶段(如排序、分组、分桶)默认受 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 前置,往往比打开落盘更有效。
开启落盘会让任务对磁盘可用空间产生依赖:磁盘写满时任务失败并可能影响同实例的其他操作,建议配合磁盘水位告警。

易错点

  • allowDiskUse 只放行不提示:不会告诉你哪个阶段超限,需结合 explain 定位后再优化
  • 把它当成性能开关:落盘后大量随机 IO 会让任务比原来更慢,收益方向完全相反
  • 未给磁盘预留空间:落盘期间临时文件写满磁盘,任务失败并波及同实例其他写入
  • 在分片集群上只在单个分片上验证:选项需通过 mongos 下发,否则部分分片仍按默认限制执行

数据来源与参考

  • MongoDB Manual: Aggregation Pipeline Limits
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌