22.MongoDB删除操作效率及相关问题验证

2023-10-27

最近遇到一个了一个MongoDB数据删除的问题,需要一次性删除上线即1.5年前~1年前的数据且之后每天清空一年过期的数据。在数据量比较大的情况下何种方式的删除效率最高是一个值得研究的问题,本文通过实际测试找出其中规律。

本文采用腾讯云mongodb集群进行验证。mongd配置较弱为2核4G,验证仅仅针对副本集不涉及分片集群。测试数据集如下,共计1000w条数据。接下来会以systime字段作为筛选条件验证影响删除操作耗时的因素都有哪些。

kfuin_beg = 0
kfuin_end = 1
for(var num = kfuin_beg; num < kfuin_end; num++){
    var kfuin_num = num+1;//主号数
    var cid_num = 10000 //1万个cid
    var session_num = 10//每个cid有10通会话
    var detail_num = 99//每个session有9条消息
    var docs = [];
    for(var i = num; i < kfuin_num; i++){
        for(var j = 0; j < cid_num; j++){
            for(var k = 0; k < session_num; k++){ 
                var kfuin_val = i + 2852000000
                var session_index_name_val = "event_session_" + kfuin_val.toString() + "_wx58b4690f0ab8193f-" + j.toString()
                var session_id_val = "session_id" + "_wx58b4690f0ab8193f-" + j.toString() + "_" +(k).toString()
                var systime_val = 1600000000000000 + j*10000 + k*1000
                docs.push({kfuin:kfuin_val,key:session_index_name_val,session_id:session_id_val,systime:systime_val})
                for(var h = 0; h < detail_num; h++){ 
                    var detail_index_val = "event_detail_" + kfuin_val.toString() + "_wx58b4690f0ab8193f-" + j.toString()
                    systime_val = 1600000000000000 + j*10000 + k*1000 + h
                    docs.push({kfuin:kfuin_val,key:detail_index_val,session_id:session_id_val,systime:systime_val})
                }
            }
            print("complete cid!!")
        }
    }
    print("insert docs!!")
    db.coll.save(docs)
}

零、MongoDB存储于删数据不释放空间?

1、MongoDB 3.6版本之后默认使用的存储引擎是WiredTiger。

①这个引擎有个特点,那就是remove删除数据不释放空间。举个例子:你现在的集合里面有1亿条数据,占用10G空间;即便你删除了其中的99999999条数据都删了,其占用的空间仍然是10GB。

②如果想彻底释放空间,最直接的方法就是删除整个集合(db.coll_0.drop())或者删除整个数据库(dropDatabases())。

③虽然磁盘利用率下不来但是对于新插入的数据只要总数据大小不超过10GB前,MongoDB都不会申请额外的硬盘空间。注:上面会有一些碎片无法完全回收,即对于“每天定时删除180d前数据这个场景”磁盘利用率还是会增长的,只不过速度会慢很多。

④如果你的MongoDB允许暂停读写操作,可以在Mongo Shell中使用compact命令释放空间。命令格式如下。

db.runCommand({'compact': '集合名'})

在MongoDB 4.4之前的版本,compact会阻塞整个库的增删改查操作,所以需要业务允许暂停全部读写才能执行;在4.4版本之后,compact命令几乎可以在除了删除集合、增删索引外的任何时候执行。

注:这是一个高危的操作,一定要充分验证/慎重。。。。。
https://www.mongodb.com/docs/manual/reference/command/compact/#dbcmd.compact

2、Mongo底层数据是如何存储的?

一个collection对应一个存储文件,同样的一个索引也对应一个单独的文件。

3、为什么drop的删除方式比remove快这么多?

remove 是对一条一条数据的逻辑删除,所以很慢。 drop 操作之间删除底层的数据库文件,然后清理一下元数据,涉及的操作很少,因此很快。

一、remove和deleteMany的区别

直接抛结论:就耗时方面似乎没有什么区别!!!

二、remove操作的耗时验证

1、无systime字段索引的删除测试

(0)访问某条具体的数据

db.coll.find({systime:1600000000022002}) 

耗时5s

(1)删除某条具体的数据

db.coll.remove({systime:1600000000022002})

耗时5s

结论:显然这个耗时是定位这条目标数据的耗时。

(2)删除其中的50W条数据

db.coll.find({systime:{"$lte":1600000005000000}}).count()
db.coll.remove({systime:{"$lte":1600000005000000}})  
#耗时19s  注:大概就是遍历用5秒+加上删除50w数据需要了14s。

结论:这个耗时应该是遍历数据用了5秒,删除50w数据用了14s。

(3)删除其中的450w条数据

db.coll.find({systime:{"$lte":1600000050000000}}).count()  
db.coll.remove({systime:{"$lte":1600000050000000}})   
#耗时190s  注:主要还是删除数据的耗时

2、有systime字段索引的删除测试

准备:创建systime字段的索引

db.coll.createIndex({systime:1})

(0)访问某条具体的数据

db.coll.find({systime:1600000000022002}) 
#瞬间 耗时1ms

(1)删除某条具体的数据

db.coll.remove({systime:1600000000022002})
#瞬间  耗时1ms

结论: 很容易理解。有索引所以瞬间定位到删除目标消息,删除的仅仅是一条所以删除操作也很快。

(2)删除其中的50W条数据

db.coll.find({systime:{"$lte":1600000005000000}}).count()
db.coll.remove({systime:{"$lte":1600000005000000}})  
#耗时15s  注:应该大部分时间都是删除消耗的;

(3)删除其中的450w条数据

db.coll.find({systime:{"$lte":1600000050000000}}).count() 
db.coll.remove({systime:{"$lte":1600000050000000}})   
#185秒  注:systime索引带来的负担还好诶;但是也确实意义不大。

结论:如果只是一个systime字段的索引给删除带来的负担感觉还好。

3、更多索引对删除效率的影响

准备:累计创建如下四个索引

db.coll.createIndex({systime:1})
db.coll.createIndex({kfuin:1})
db.coll.createIndex({key:1})
db.coll.createIndex({key:1,systime:1})

(1)删除其中的50w条数据

db.coll.find({systime:{"$lte":1600000005000000}}).count()
db.coll.remove({systime:{"$lte":1600000005000000}})  
#耗时22s  注:过多的索引确实会对删除效率产生负面影响,这个额外的三个索引是耗时变为原来的1.5倍左右。

(2)删除其中的450w条数据

db.coll.find({systime:{"$lte":1600000050000000}}).count() 
db.coll.remove({systime:{"$lte":1600000050000000}})   
#250秒 注:过多的索引确实会对删除效率产生负面影响,这个额外的三个索引是耗时变为原来的1.5倍左右。

结论:过多的索引确实会对删除效率造成影响;对于测试中额外多增加了三个索引删除耗时约为没有这三个索引的1.3~1.5倍左右。

4、删除操作的集群资源消耗情况

这个操作看起来主要消耗的是cpu,对于测试集群目标分片的cpu消耗在90%+。

3、结论

1、remove和deleteMany在效率上没有什么区别,以后统一用remove好了。

2、拆开来讲删除操作需要的耗时主要包括两块:①遍历到目标数据的耗时 ②删除消息的耗时。对于前者 如果删除一条数据的话就理解为定位到目标数据;如果有索引的情况下就理解为定位到需要删除数据的起始删除目标位置点。

注:oa环境低配机器无索引情况下删除100w条数据大概需要30s。
注:oa环境低配机器无索引情况下遍历100w数据需要0.5s(1000w数据5s)。

3、建立筛选字段的索引确实会对寻找删除数据、删除数据位置点都有帮助;但同时索引也会给删除操作带来负担。

4、究竟什么删除策略好还是要结合你的数据集和想要删除的数据集。

case1:数据集很大一次性删除很少的数据 —— 显然需要建立索引。

case2:数据集很大删除的数据也很多 —— 此时定位删除位置点的耗时就显得不那么重要了,主要耗时都在删除操作本身上了;极端情况下如果我们要删除目标数据集中的80%以上的数据这个时候建不建索引影响不大。

5、现在结论也比较清晰了。

(1)第一波删除的时候大概要清理其中的三分之一的数据,这个时候有systime索引更好没有感觉问题也不大(遍历的耗时和删除的耗时速度起码差了60倍)。

(2)后续如果你需要systime维度的每天删除一波过期数据应该还是要systime更好。

(3)这个时候关注重点应该是测试目标集群对一个索引后台创建索引、删除数据的资源消耗的情况,如果没问题就可以实施了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

22.MongoDB删除操作效率及相关问题验证 的相关文章

随机推荐

  • 使用openssl_encrypt方法替代mcrypt_encrypt做AES加密

    mcrypt encrypt在php7 1中已被废弃 需要使用openssl encrypt代替 mdecrypt generic版 public function encrypt cbc str iv encryptKey module
  • java8中stream()的使用案例

    Test public void t1 List
  • VS2008中的 fatal error C1902: 程序数据库管理器不匹配

    因为VC Bin 下没有 msobj80 dll mspdb80 dll mspdbcore dll mspdbsrv exe 这四个文件 解决的方法 1 gt 直接从Common7 IDE 下复制这四个文件到VC Bin 下即可解决 2
  • Android-四大应用组件之Activity

    一 理论概述 Activity的理解 二 Intent和IntentFilter的理解 显示意图 当目标组件是当前应用的 则用显示意图 隐式意图 当目标组件是其他应用的 则用隐式意图 三 相关API 四 Activity的启动流程 通过Ac
  • 网络安全工具——Wireshark抓包工具

    文章目录 一 Wireshark抓包介绍 1 WireShark简介 2 WireShark的应用 3 WireShark抓数据包技巧 二 Wireshark抓包入门操作 1 常见协议包 2 查看本机要抓包的网络 3 混杂模式介绍 4 如何
  • stratascratch刷题1 salaries difference && Finding Updated Records

    1 解题 select select max salary from db employee join db dept on db employee department id db dept id where department mar
  • 接口测试的基础(网络传输知识与协议篇)

    接口测试的基础 测试人员对于接口测试的理解总是停留在工具使用层面 很多情况下 测试人员会花很大的 代价去学习一个工具 而测试工具本身的局限性 又导致测试人员陷入想直接用现成的测试框架 却又无法进行扩展的僵局 最后由于项目的特殊性等客观因素
  • ping命令中ICMP协议包的分析

    UDP收发以及所需要的ARP协议已经全部实现 接下来让咱们的协议栈支持ping 俗称能ping通 ping的请求和发送实际是ICMP协议的一个子集 ICMP可以参考ICMP数据包结构 Focus 新浪博客 在IP头中ICMP协议的标识是01
  • springboot项目读取 resource下面的json文件,并且解析

    在Spring Boot项目中 如果要读取src main resources目录下的JSON文件 可以使用ResourceLoader来加载文件 并使用Jackson库将JSON文件解析成Java对象 以下是一个简单的示例代码 impor
  • Type-C协议简介(CC检测原理)

    1 简介 越来越多的手机开始采用Type C作为充电和通信端口 Type C连接器实物和PIN定义如下图 目录 1 简介 Type C连接器中有两个管脚CC1和CC2 他们用于识别连接器的插入方向 以及不同的插入设备 本文介绍CC的基本识别
  • Bootrom概述

    1 Bootrom 是指on chip bootrom 在CPU芯片内部 内嵌有小的boot程序 bootloader 类似于PC机主板上的BIOS的存储区域 2 Bootloader怎么得到 如果对开发板有些改动 还能使用开发板的boot
  • solidity学习过程---msg

    solidity 5 0 remix测试 个人学习 欢迎指正 msg 研究了好一会 感觉还是有点困惑 msg sender 当前合约的调用者 1 部署合约的地址 2 调用该合约的地址 msg value 随消息发送的 wei 的数量 其实并
  • 【Spark NLP】第 15 章:聊天机器人

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • sonarQube详细安装

    目录 安装前提 将zip包scp到服务器 解压sonar的zip包 修改配置 创建用户sonar 将sonar目录授权给sonar用户 执行命令 查看日志 遇到的问题 今天学习了一下sonar 想看看代码质量检查工具的使用 安装前提 需要j
  • python笔记9--socket初步使用

    python笔记9 socket初步使用 1 介绍 2 源码案例 2 1 tcp c s 案例 2 2 udp c s 案例 3 说明 最近需要写个c s小应用 因此看了下socket编程 把学习的笔记贴在此处以便于后续查阅 1 介绍 本文
  • Mysql服务的安装

    本文适用于新手 小白 而且专业术语不到位 本文内容可能无法解决教程外其他问题 望多包涵 多图警告 此教程适用于windows系统 教程流程 安装时 1 下载安装包 这个是下载链接 MySQLhttps www mysql com 打开界面后
  • ubuntu连接mysql命令_远程服务器 ubuntu 安装 mysql 及连接使用

    远程服务器 ubuntu 安装 mysql 及连接使用 MySQL是最流行的开源关系数据库管理系统 它速度快 容易使用 容易扩展 并且流行的LAMP和LEMP的一部分 这篇指南讲解了如何在 Ubuntu 20 04上安装和保护 MySQL
  • SQL 取数值小数后两位,但不四舍五入。

    例 1 67789 结果要显示为 1 67 select round 1 67789 2 1 1 67 语法 ROUND numeric expression length function 参数 numeric expression 精确
  • k8s滚动更新

    1 编写一个yaml文件 vi deployment nginx yaml apiVersion apps v1 kind Deployment metadata labels app nginx name nginx namespace
  • 22.MongoDB删除操作效率及相关问题验证

    最近遇到一个了一个MongoDB数据删除的问题 需要一次性删除上线即1 5年前 1年前的数据且之后每天清空一年过期的数据 在数据量比较大的情况下何种方式的删除效率最高是一个值得研究的问题 本文通过实际测试找出其中规律 本文采用腾讯云mong