假设我有两个集合,A和B.除此之外,其中一个集合(集合A)有一个数组,其单元格包含带有少量键的子文档。
我还有一个脚本将通过队列(MongoDB外部),在集合B上插入其项目,并使用$push
将这些项目中的任何相关信息推送到集合A中的数组的子文档中。随着脚本的运行,集合A中文档的大小会显着增长。
问题似乎是,只要文档不符合其分配的大小,MongoDB就会在内部移动它,但它不会释放它以前占用的空间 ---新的MongoDB文档除非我运行compact
或repairDatabase
命令,否则不会使用该空格。
就我而言,脚本似乎很快就烧掉了我的磁盘空间。它将几个项目插入到集合B中,然后尝试插入集合A中的文档,并且(我猜)重新定位所述文档而不重用其旧点。也许每次都不会发生这种情况,使用填充,但是当这些文档的大小约为10MB时,这意味着每次发生时它会烧掉相当大的数据块,即使实际数据量仍然很小。这个过程会在几分钟内耗尽我的(相当小的,公认的)数据库。
每次发生这种情况时都需要compact
或repairDatabase
命令是笨拙的:磁盘上有 空间,我希望MongoDB能够在不明确请求的情况下使用它。为数组中的子文档提供单独集合的替代方法可以解决这个问题,无论如何可能是一个更好的设计,但是需要我进行我想避免的连接,这是NoSQL的优势之一。
那么,首先,MongoDB是否真的按照我上面描述的方式使用空间?第二,我是以错误的方式接近这个吗?也许我可以设置一个参数来让MongoDB自动重用这个空间;如果有,是否可以使用它?第三,我还缺少其他更合适的设计方法吗?
答案 0 :(得分:1)
您提出的大部分问题都应该已经知道(Google搜索会提出100条链接,包括关于这个问题的关键博客文章)但是在这种情况下试图使用MongoDB,这个演示文稿应回答90%的问题:http://www.mongodb.com/presentations/storage-engine-internals
至于通过设置等解决问题,这里不太可能,2个尺寸的功率对于像这样增长的阵列不会有帮助。所以回答:
也许我可以设置一个参数来让MongoDB自动重用这个空间;如果有,是否可以使用它?
我会说不。
第三,我还缺少其他更合适的设计方法吗?
对于类似的内容,我建议使用单独的集合将每个数组元素存储为独立于父文档的新行。
答案 1 :(得分:0)
Sammaye的建议是正确的,但我需要做更多的挖掘来了解这个问题的原因。这是我找到的。
那么,首先,MongoDB是否真的按照我上面描述的方式使用空间?
是的,但那不符合预期。请参阅错误SERVER-8078及其(非显而易见的)重复SERVER-2958。频繁的$push
操作会导致MongoDB对文档进行随机播放,并且在没有compact
或repairDatabase
命令的情况下,它们的旧位置不会重复使用。
其次,我是以错误的方式接近这个吗?也许我可以设置一个参数来让MongoDB自动重用这个空间;如果有,是否可以使用它?
对于$push
的某些用法,usePowerOf2Size
选项最初会消耗更多内存,但会更好地稳定(请参阅SERVER-8078上的讨论)。它可能不适用于一直倾向于增长的数组,无论如何这都是一个坏主意,因为文档大小有上限。
第三,我还缺少其他更合适的设计方法吗?
如果数组将有数百或数千个项目,或者它的长度是任意的但可能很大,那么将其单元格移动到不同的集合会更好,尽管需要额外的数据库调用。 / p>