统计接口直接超时,日志里是 Exceeded memory limit of 104857600 bytes,管道里只有 match 和 group 两个阶段。日志里能对上时间点,这种反而好排。
group 阶段要在内存里维护所有分组键,超过 100MB 就直接报错,allowDiskUse 没开,前面也没有过滤把数据量压下去。这一点先确认清楚,后面就不用反复试。
db.orders.aggregate([
{ $match: { status: 'paid' } },
{ $group: { _id: '$user_id', n: { $sum: 1 } } }
], { allowDiskUse: true });
「MongoDB 聚合内存超限」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
报错里带路径的,先去看那个路径在不在、权限对不对。同一份配置存在多处的,先确认改的是被加载的那一份。
新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
处理上按这个顺序:把 match 和 project 阶段提到管道最前面先瘦身;group 之前先把不需要的字段和行过滤掉;确实需要大分组时给这次的聚合加上 allowDiskUse。
结果对不对很好判断,同样的聚合两秒内返回,日志里不再出现内存超限的报错。
