我已经看到有关压缩MongoDB数据库文件的问题,以及关于通过删除整个文档来重用空间的问题,但是我找不到任何关于从文档中删除字段是否会为其他新文档释放空间的信息。
具体来说,我有一些文档代表某些操作的结果,包含有关它的元数据,操作的最终结果,以及一个大而详细的日志。该日志比所有其他字段大几个数量级。我想保留其他字段,但是过了一段时间后,日志占用的空间超出了它们的价值,所以我想删除它们 - 但只有在有意义的情况下才能删除它们。
这会做我想要的吗?或者我是否需要创建新文档作为旧文档的副本但没有大字段,并删除旧文档?
答案 0 :(得分:2)
基本概念是MongoDB为文档分配记录空间,允许该文档在适当的位置增长。文档大小与记录之间的差异称为 padding 。充足的填充可以减少文档移动对性能的影响。
正如@NeilLunn所推测的那样,从文档中删除字段不会将该记录空间返回到空闲列表。这在Record Padding的文档中也有说明:
如果更新操作导致文档大小减小,例如,如果执行$ unset或$ pop更新,则文档将保留在原位并有效地具有更多填充。如果文档保持此大小,则在执行压缩或修复数据库操作之前不会回收空间。
有(如MongoDB 2.2)两种服务器端集合分配策略:
根据Padding Factor分配记录空间。 MongoDB根据历史文档增长自动计算集合paddingFactor
。文档大小乘以填充因子以确定所需的记录分配,因此记录大小会有所不同。这是MongoDB生产版本到2.4的默认分配策略。
根据Power Of 2 Sizes分配记录空间。在这种情况下,MongoDB以2的幂分配记录空间(例如,4,8,16,......最多4Mb,然后以1Mb为增量)。使用此分配策略的记录大小将有限,这样可以更频繁地重复使用频繁删除或文档增长的集合的可用空间。这是MongoDB 2.2和2.4中的可选分配策略,将是MongoDB 2.6中的默认分配。
除了服务器端集合分配策略之外,还可以添加manual padding来补充任何一种内置分配方法。例如,如果您的文档开始非常小并且在达到典型大小之前快速增长,您可能希望允许这种增长。
值得注意的是,分配策略仅在插入或移动文档时(即,在分配记录空间时)考虑。启用usePowerOf2Sizes
不会影响集合中的任何历史记录分配,只会影响新分配。您还可以指定在compacting a collection时使用的起始paddingFactor
或paddingBytes
。
具体来说,我有一些文档代表某些操作的结果,包含有关它的元数据,操作的最终结果,以及一个大而详细的日志。该日志比所有其他字段大几个数量级。我想保留其他字段,但是过了一段时间后,日志占用的空间超出了它们的价值,所以我想删除它们 - 但只有在有意义的情况下才能删除它们。
这会做我想要的吗?或者我是否需要创建新文档作为旧文档的副本但没有大字段,并删除旧文档?
你有几个选择:
repairDatabase
以回收分配给已删除日志字段的过多记录空间在上述所有情况中,我建议使用日志数据为集合启用usePowerOf2Sizes
选项,因为此分配策略将有助于重用可用空间。
如果可能,调整数据模型将是最有效的方法。使用powerOf2Sizes,复制和重新保存文档可以减少运行修复的需要,但作为最后的手段,您可以进行定期修复。
答案 1 :(得分:1)
将前缀加上“不是真正的答案”,因为这可能留给了对实现有更多了解的人,因此很可能是来自MongoDB本身的人。
我在这里工作的一般前提是“不”。很大程度上是因为你所知道的关于文件删除和空间被移动到“自由列表”,据我所知,另一个文件可以放在那个空间,只要它“小”足以使用有空间被释放了。
一般的前提是“文档”是需要使用连续存储的东西,并考虑诸如“手动填充”之类的概念,以便故意为文档分配空间,以便它不会“移动”似乎预测一旦你减少了文档大小,它就不会被移动到占用更少空间的地方。
这是一个非技术性的观察,但是观察我所知道的部分。考虑到您的用例,尽管可能有其他选择。
正如您所提到的,您拥有“特别大”的日志信息,经过一段时间后可能无法进一步实际使用。由于这是您认为可以丢弃的部分,因此将其放入单独的集合中可能是值得的。
当然,您需要考虑从“嵌入式”模型中改变您的方法,但考虑到您所说的情况,这将导致实际的文档删除。因此,更加符合MongoDB重新声称空间的方式。
或者,正如您所建议的那样,手动创建压缩副本同样会产生相同的结果。但是,我们可能会等待专家们的参与。