navicat中mongo显示表的存储大小异常的大?

不知道,大家有没有没发现,在使用navicat的时候,会发现,在mongo中,一个数据表,明明没有那么多的数据,但是,存储大小特别大。

比如下述表,一共49个文档,存储大小却有31.48M,我可以肯定的是,一个文档,最多不超过5k。那么,这么异常的存储大小大小哪里来的呢?

image.png

复现步骤

当我发现这个问题之后,我就想研究一下。
那么怎么复现呢?

我首先做了一个测试数据库
正常存入数据,发现存储大小是正常值。

那么,我还做了哪些操作呢?
对了,我记得有人使用remove方法,删除了很多mock数据,难道,是remove方法?

所以,我执行了remove方法,将数据删除了,惊奇的发现,果然如此,数据0条,存储大小依旧存在,不是预料之中的0。

那么,是因为remove方法导致的?

重新操作,创建一些数据,发现,是的,就是这个原因。

复现到此为止,接下来,来揭秘存储大小和remove方法的关系吧

什么是存储大小?什么是内存总大小?

从上述的图中,我们看到两个好玩的数据,内存中的总大小(内存总大小),存储大小。
image.png

那他们分别什么是什么东西呢?

  • 存储大小
    • 存储大小是指该集合中所有文档实际占用的磁盘空间大小
    • 内容: 存储的数据文件、索引文件、预分配的空间等
    • 通过 db.stats()db.collection.stats() 查询
  • 内存总大小
    • 内存总大小是指 MongoDB 在内存中使用的空间
    • 包含内容: 数据库缓存、索引缓存、操作内存等
    • 通过 **db.serverStatus()** 查询。

所以,存储大小和内存总大小分别代表磁盘和内存中的不同资源使用情况,对数据库性能和资源管理有重要影响。

存储大小和内存总大小不一致的原因

有了上述的了解,我们可以得知,存储大小和内存总大小可能存在一部分的不一致,原因如下:

  1. MongoDB使用了预分配机制,在集合中插入文档时会预先分配一定大小的空间。如果集合中有很多已经删除的文档,但是它们占用的空间并未被释放,那么这些空间将会被视为已分配的空间并计入内存总大小,但不会计入存储大小。
  2. MongoDB还会对集合进行索引,索引也会占用一定的空间。这些空间也会计入内存总大小,但不会计入存储大小。
  3. MongoDB使用BSON格式进行文档存储,而这种存储格式是二进制码压缩的,因此相对于JSON格式来说,它可以更有效地利用存储空间。这就是为什么存储大小会比内存总大小小很多。

存储大小和内存总大小不一致与remove()的关系

有些小伙伴说了,那根据你的分析,不就跟remove()方法没关系了吗?

敲黑板了,同学们🧑‍🎓

以上只是正常的大小偏差,我们要解决的是内存大小异常的大的问题。

所以,remove()有什么特殊呢?

经过查阅文档得知:

在MongoDB中,执行remove()方法删除集合中的文档并不会立即释放硬盘空间,而是将这些空间标记为可复用的状态。因此,即使你执行了remove()方法删除了文档,MongoDB所占用的空间大小可能仍然没有变化。
同理,deleteOne() 方法和 deleteMany() 方法也都是只会删除符合条件的文档,不会删除集合上的索引。

所以,回想一下问题复现,有人删除了大量的mock数据,注意⚠️:大量的mock数据,
导致了他们存在很多索引及占用空间,在删除的时候,没有被删除掉。

这就是存储大小异常的大的原因。

如何释放存储大小中无用的数据

有问题,总要解决的。

万事总用方法。

想要释放这些已经删除的文档所占用的硬盘空间,可以通过以下两种方式:

方法1: 执行compact命令

执行compact命令可以将已经删除的文档所占用的硬盘空间进行整理和压缩,从而释放被删除文档所占用的硬盘空间。在MongoDB 3.6及以后版本,该命令已被弃用,例如:

db.runCommand({ compact: "collectionName" })
//eg:释放data_645b4501ef86ee0fec16a106表的存储大小
db.runCommand({ compact: 'data_645b4501ef86ee0fec16a106' })

方法2:执行repairDatabase()命令

执行repairDatabase()命令可以对整个数据库进行修复和优化,包括清除已经删除的文档所占用的硬盘空间。但是,该命令会对整个数据库进行锁定,可能会导致一些性能问题。
应该在非高负载时段执行该命令。例如:

db.repairDatabase()

需要注意的是,在执行以上两种方式之前,请务必备份好你的数据以防止误操作造成数据丢失。

总结:

首先:存储大小和内存总大小是两回事。
其次:remove()、deleteOne()、deleteMany()都只能删除符合条件的文档,不删除索引。
最后:这只是在测试环境的操作,建议大家,谨慎使用物理删除方法,如需使用,请慎之再慎。

最后一提

都看到这里了,看来你对这篇文章很感兴趣哈!

如果能给个一键三连,这将是对我很大的鼓励。

当然,如果你很感兴趣

也可以关注公众号与我联系

公众号:乾复道在编程

  • 73
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 81
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 81
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乾复道

与君共勉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值