我有一个拥有5200万条记录的用户集合。每个用户文档都有一个注释列表,并comment_id
具有唯一索引。
{
_id:123,
user_name:"xyz",
comments:[
{
comment_id:123,
text:"sd"
},
{
comment_id:234,
text:"sdf"
}
......,
(63000 elements)
]
}
在totalIndexSize
该的comment_id
指数为104GB。在52M中,我有大约100个文档在注释数组中有63000个元素。
我的目的是删除旧注释,并将注释数组的大小减少80%以上。之前当我尝试使用此查询更新文档时
db.user.updateOne({_id:_id},{$set: {"comments":newCommentsArray}},upsert=True)
这里的newCommentsArray大小约为400。执行此操作大约需要130秒。
我的问题是:
1)可能是上述更新查询花费了130秒的原因。是因为comment_id
字段具有巨大的唯一索引大小吗?(我相信用新的注释数组更新注释数组将尝试重新排列所有已删除的63000元素的索引,并将新元素插入索引中。)
2)我还有另一种方法$pull
,基本上是从注释数组中提取100条注释,等待5秒钟,然后执行下一批100条注释。您如何看待该解决方案。
3)如果上述解决方案不好,您能否建议一种将注释数组减少80%以上的好方法。
您有一个巨大的索引comment_id
是因为您有多键索引
MongoDB为数组中的每个元素创建一个索引键。
在您的情况下,_id
索引的大小comment_id
为avg ~100/per document
〜1GB ,即为(获取〜104GB)
1)可能是以上更新查询花费了130秒的原因
Mongodb存储具有B树结构的索引。B树属性:
Algorithm Average Worst case
Space O(n) O(n)
Search O(log n) O(log n)
Insert O(log n) O(log n)
Delete O(log n) O(log n)
这意味着,为了插入注释索引,O(log n)
在最坏的情况下,MongoDB需要进行迭代(每个项目约25次迭代)。
2)我还有另一种使用$ pull的方法,它基本上是从注释数组中提取100条注释,等待5秒钟,然后执行下一批100条注释。
当注释被索引时,它将很快(记住O (log n)
属性)。不必等待5秒钟,因为从MongoDB 3.0开始,它使用了多粒度锁定,这意味着仅锁定受影响的文档。
另外,您可以使用以下$push
运算符来减少:
db.user.update({ },{$push: {comments: {$each: [ ], $slice: -400}}})
这将插入[ ]
(在这种情况下为0项)项,并从末尾切片400项
3)如果上述解决方案不好,您能否建议一种将注释数组减少80%以上的好方法。
即使减少注释数组,WiredTiger也不会将不需要的磁盘空间释放给操作系统。
db.user.dropIndex({ "comment_id" : 1 })
警告:由于v4.2在操作期间会在指定集合上获得排他锁。集合上的所有后续操作都必须等到db.collection.dropIndex()释放锁。
在v4.2之前,此命令将在受影响的数据库上获得写锁定,并将阻止其他操作,直到完成为止。
还是运行紧凑
警告: compact
阻止当前正在运行的数据库的操作。仅compact
在计划的维护期内使用。此外,您还必须user
使用目标集合上的紧凑特权操作进行身份验证
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句