不知道,大家有没有没发现,在使用navicat的时候,会发现,在mongo中,一个数据表,明明没有那么多的数据,但是,存储大小特别大。
比如下述表,一共49个文档,存储大小却有31.48M,我可以肯定的是,一个文档,最多不超过5k。那么,这么异常的存储大小大小哪里来的呢?
复现步骤
当我发现这个问题之后,我就想研究一下。
那么怎么复现呢?
我首先做了一个测试数据库
正常存入数据,发现存储大小是正常值。
那么,我还做了哪些操作呢?
对了,我记得有人使用remove方法,删除了很多mock数据,难道,是remove方法?
所以,我执行了remove方法,将数据删除了,惊奇的发现,果然如此,数据0条,存储大小依旧存在,不是预料之中的0。
那么,是因为remove方法导致的?
重新操作,创建一些数据,发现,是的,就是这个原因。
复现到此为止,接下来,来揭秘存储大小和remove方法的关系吧
什么是存储大小?什么是内存总大小?
从上述的图中,我们看到两个好玩的数据,内存中的总大小(内存总大小),存储大小。
那他们分别什么是什么东西呢?
- 存储大小
- 存储大小是指该集合中所有文档实际占用的磁盘空间大小
- 内容: 存储的数据文件、索引文件、预分配的空间等
- 通过
db.stats()
和db.collection.stats()
查询
- 内存总大小
- 内存总大小是指 MongoDB 在内存中使用的空间
- 包含内容: 数据库缓存、索引缓存、操作内存等
- 通过
**db.serverStatus()**
查询。
所以,存储大小和内存总大小分别代表磁盘和内存中的不同资源使用情况,对数据库性能和资源管理有重要影响。
存储大小和内存总大小不一致的原因
有了上述的了解,我们可以得知,存储大小和内存总大小可能存在一部分的不一致,原因如下:
- MongoDB使用了预分配机制,在集合中插入文档时会预先分配一定大小的空间。如果集合中有很多已经删除的文档,但是它们占用的空间并未被释放,那么这些空间将会被视为已分配的空间并计入内存总大小,但不会计入存储大小。
- MongoDB还会对集合进行索引,索引也会占用一定的空间。这些空间也会计入内存总大小,但不会计入存储大小。
- 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()都只能删除符合条件的文档,不删除索引。
最后:这只是在测试环境的操作,建议大家,谨慎使用物理删除方法,如需使用,请慎之再慎。
最后一提
都看到这里了,看来你对这篇文章很感兴趣哈!
如果能给个一键三连,这将是对我很大的鼓励。
当然,如果你很感兴趣
也可以关注公众号与我联系
公众号:乾复道在编程