MongoDB删数据---一个无聊的测试
上周五的时候,线上的一个MongoDB集群需要删除部分数据,这个MongoDB集群本身是个分片集群,包含10个分片,架构如下:
集群的总体节点情况如下:
15个mongos
5个mongoc
10个分片,每个分片7副本
在这样的一个集群上,需要删除一个集合的部分数据,包含数据记录977w条,删除的条件是分片键。业务给出的待删除记录为:
db.test.find({pid:xxxxxxx})
其中,pid是集合的分片键。
分析:
因为是按照分片键进行删除,所以如果我们执行一条删除语句,理论上会将删除的请求分发到每个shard上,然后分别执行删除操作,最后汇总起来。
实际操作过程中,我们采用的删除语句如下:
db.test.remove({pid:xxxxxxx})
实际执行时间:977w满足条件的数据全部删除,总计不到2分钟。(这个时间具有参考意义,大家可以记录下)
延伸
这里,就出现了一个问题,在MongoDB中,常用的删除语句有2中,分别是deleteMany语法和remove语法,那么这两种语法,到底哪个更快一点,更高效呢?
我们先来分析这两个语法:
首先:db.collection.deleteMany()
这个语法的使用方法如下:
db.collection.deleteMany( <filter>, { writeConcern: <document>, collation: <document> } )
其中:
filter写条件,如果删除所有文档,则写{}即可;
writeConcern、collation写具体的删除配置,也可以不写。
返回值:
返回一个文档,包含一个acknowledged 字段,如果在writeConcern条件下操作成功,则为true,如果操作失败,则为false;另外有一个deletedCount字段,包含删除的文档记录条数
再来看:db.collection.remove()
---------删除一条记录-------- db.collection.remove( <query>, <justOne> ) ----------删除多条记录------ db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document>, collation: <document> } )
相比deleteMany,remove方法多了个选项,有一个bool类型的justOne选项,如果设置为true,则只删除满足条件的一条文档。
deleteMany方法无法实现只删除一条文档,如果非要实现,请使用db.collection.deleteOne方法。
那么这两个语法,到底哪个高效呢?下面我简单做了个实验:
1、给test、test1两个集合分别插入20w条数据;
2、分别使用deleteMany和remove方法删除大于1000的记录,总计包含19w多;
3、记录操作开始时间和结束时间,对比整体的时间消耗。
得到的实验结果如下:
--------------remove方法测试------------ test1:PRIMARY> for (var i=1 ;i<=200000 ; i++){ db.test.insert({"number":i})} WriteResult({ "nInserted" : 1 }) ---开始时间 test1:PRIMARY> new Date() ISODate("2021-11-02T06:29:09.995Z") test1:PRIMARY> db.test.remove({'number':{$gt:1000}}) WriteResult({ "nRemoved" : 199000 }) ---结束时间 test1:PRIMARY> new Date() ISODate("2021-11-02T06:29:25.412Z") remove总计时间:15.417s --------------deleteMany方法测试------------ test1:PRIMARY> for (var i=1 ;i<=200000 ; i++){ db.test1.insert({"number":i})} WriteResult({ "nInserted" : 1 }) ---开始时间 test1:PRIMARY> new Date() ISODate("2021-11-02T06:48:08.511Z") test1:PRIMARY> db.test1.deleteMany({'number':{$gt:1000}}) { "acknowledged" : true, "deletedCount" : 199000 } ---结束时间 test1:PRIMARY> new Date() ISODate("2021-11-02T06:48:24.204Z") deleteMany总计时间:15.693s
总体来看:
1、deleteMany和remove方法删除数据的效率差不多。
2、deleteMany语法执行完成之后,会告知执行是否失败,并告知记录条数;而remove方法执行之后,只给出记录条数。
3、deleteMany语法无法删除一个文档,而remove方法可以删除单个文档