mongodb - 聚合因内存错误而失败
Posted
技术标签:
【中文标题】mongodb - 聚合因内存错误而失败【英文标题】:mongodb - aggregate failed with memory error 【发布时间】:2016-06-02 09:14:25 【问题描述】:我正在尝试使用 id 字段在我的分片集合中查找重复项,该字段属于这种模式 -
"id" :
"idInner" :
"k1" : "v1",
"k2" : "v2",
"k3" : "v3",
"k4" : "v4"
我使用了以下查询,但收到“异常:超过 $group 的内存限制,但不允许外部排序。通过 allowDiskUse:true 来选择加入。”错误,即使我在查询中使用了“allowDiskUse:true”。
db.collection.aggregate([
$group:
_id: id: "$id" ,
uniqueIds: $addToSet: "$_id" ,
count: $sum: 1
,
$match:
count: $gte: 2
,
$sort : count : -1 ,
$limit : 10
],
allowDiskUse : true
);
有没有其他方法可以得到我想要的,或者我应该在上面的查询中传递什么?谢谢。
【问题讨论】:
_id
字段本身始终使用“唯一”约束进行索引。它不能包含重复项。
这不是“_id”字段,在我的情况下,我默认让 mongo 填充。我有自己的“id”(不带下划线),其中包含我的密钥。
您的群组中真的需要uniqueIds: $addToSet: "$_id"
吗?这可能会缓解一些内存问题。
我的收藏中有大约 200 万个文档。注释掉 'uniqueIds: $addToSet: "$_id" ' 以及使用 '_id: "$id.idInner"' 仍然会出现同样的错误。
如果你想要基于你自己的“id”的集合中的唯一数据,我建议在它上面创建唯一索引。这是确保收集中唯一文档的最有效方式。
【参考方案1】:
首先在管道中运行$match
,以仅保留某个范围之间的文档,例如id.idiInner.k1
,以便您仅获取该范围的结果。由于您对 id
键上的重复项感兴趣,因此所有重复的文档都将满足此条件。看看你应该缩小这个范围多少,然后在下一个范围内运行它等等,直到你覆盖所有文档。
如果这是您必须经常做的事情,请通过声明范围、循环输入它们、保留每次运行的重复项并最终合并结果来实现自动化。
另一个快速破解/技巧是绕过 mongos 并直接在每个 shard 中运行聚合。这样做会将您的文档粗略地(假设分片平衡良好)限制为 docs/number_of_shards,并且您可能会克服内存限制。在第二种方法中,我假设您的分片键是 id 键,但是如果不是,那么这种方法将不起作用,因为相同的重复文档将分散在分片中。
【讨论】:
感谢您建议使用 $match 来缩小结果范围。这帮助我得到了我想要的。【参考方案2】:请在运行命令中使用allowDiskTrue。
db.runCommand(
aggregate: "collection",
pipeline: [
$group:
_id: id: "$id" ,
uniqueIds: $addToSet: "$_id" ,
count: $sum: 1
,
$match:
count: $gte: 2
,
$sort : count : -1 ,
$limit : 10
],
allowDiskUse: true
)
让我知道这是否适合你。
【讨论】:
抱歉,我刚刚试了一下,效果很好。谢谢。以上是关于mongodb - 聚合因内存错误而失败的主要内容,如果未能解决你的问题,请参考以下文章