MongoDB 3.2数据迁移遇getMore/aggregate大小超限 需构建对应聚合查询
问题原因分析
报错1:getMore返回BSON超过16MB
该报错并非单个文档大小超限,你排查单个文档大小无异常是正常的,问题出在MongoDB 3.2版本中find游标单次getMore请求返回的批次总数据大小超过了16MB的默认限制。
报错2:聚合BufBuilder超过64MB限制
MongoDB 3.2版本默认每个聚合阶段的内存使用上限为64MB,你的分组操作涉及数据量过大,触发了内存上限报错。
解决方案
1. 修复数据迁移报错
- 迁移读取数据时主动限制游标批次大小,避免单次拉取数据过多,示例如下:
user=db.getSiblingDB('DB') // 调整batchSize数值,控制单次拉取的总数据量不超过16MB user.Coll.find().batchSize(50).forEach(function(obj) { // 单条或小批量写入目标集合 user.targetColl.insertOne(obj); })
- 若使用批量写入,需控制单次插入的文档总大小不要超过16MB。
2. 修复聚合报错&构建符合要求的查询
聚合操作开启allowDiskUse: true参数,允许聚合阶段将超出内存的数据临时落盘,即可规避64MB内存限制。
对应参数生成的聚合查询语句(Mongo Shell语法)如下:
// 连接数据库 var db = connect("mongodb://user:pass@hostname:27017/DB?authSource=admin"); var coll = db.getCollection("Coll85"); var result = coll.aggregate([ // 匹配条件阶段 { $match: { TaskInstanceID: 851504966, _version: { $ne: -1 }, MatchStatus: { $ne: 21 }, ViewData: { $ne: null }, "ViewData.CombinedAndIsPaired": { $ne: true } } }, // 投影阶段,仅保留需要的字段,减少后续阶段数据量 { $project: { InternalComment1: 1, InternalComment2: 1, InternalComment3: 1, ExternalComment1: 1, ExternalComment2: 1, ExternalComment3: 1, ViewData: 1 } }, // 分组阶段 { $group: { _id: { "Status": "$ViewData.Status", "InvestmentType": "$ViewData.Investment Type" }, // 统计分组内文档数 groupCount: { $sum: 1 }, // 收集分组内所有指定字段的内容 items: { $push: { InternalComment1: "$InternalComment1", InternalComment2: "$InternalComment2", InternalComment3: "$InternalComment3", ExternalComment1: "$ExternalComment1", ExternalComment2: "$ExternalComment2", ExternalComment3: "$ExternalComment3", "ViewData.Side0_UniqueIds": "$ViewData.Side0_UniqueIds", "ViewData.Side1_UniqueIds": "$ViewData.Side1_UniqueIds" } } } } ], { // 开启磁盘使用,突破64MB内存限制 allowDiskUse: true }).toArray(); // 输出查询结果 printjson(result);
如果需要将结果写入指定集合,只需在聚合管道末尾添加{ $out: "输出集合名" }阶段即可。
内容的提问来源于stack exchange,提问作者Yogesh J
相关产品推荐
相关产品推荐

