我正在考虑将“可观”文档的集合分为2个集合(通常查询摘要字段,而从不查询明细字段/文档数组)。目的是减少平均文档大小,从而减少“工作集”的内存占用量和收集扫描时间。文档将从约9.5kB减少到约2.7kB,减少了3.5倍(内存BSON大小)。
这应该以相同的3.5倍因数减少对wiredTiger缓存的要求,因此需要在计算机中减少3.5倍的内存。还会将收集扫描查询的速度提高差不多吗?由于更新/插入操作在脱机批处理过程中运行,因此很少执行,也不会对性能造成影响。
这适用于在FreeBSD上运行的MongoDB 4。该Web应用程序位于php7.3中,但这并不相关。
我目前有100万个以上大小的文档。解压缩后,磁盘上大约有3.5GB,内存中有7GB。当前的服务器具有16GB RAM,但这正成为一个问题,并且是动机的一部分,因为预计文档数量将迅速增长到400万,然后再增长到800万。
该应用程序主要是“切片和骰子”查询界面。用户界面中的大约20个不同“过滤器”会在各个摘要字段上推动查询条件。它们全部都被索引了,包括一些化合物和一些用于小数组的多键,但是由于“ UI过滤器”可以以任何组合使用,因此索引不能总是有帮助,因为为每种可能的字段组合创建复合索引是不现实的。
收集文档的结构是5个大型的详细子文档数组(占子文档总大小的70%),外加许多计算出的“摘要字段”。摘要字段是通过缓慢的脱机过程从大型详细信息子文档中计算出来的。很好,不是问题。这些查询仅针对摘要字段,而不针对原始子文档。但是,我们最终进行了常规的“完整馆藏扫描”。随着收集规模的增加,这些开始放缓。当前约10秒钟,此时没有可用的索引,并且结果几乎包含完整的集合。这太慢了,无法进行真正的交互。计数对于应用程序至关重要,而且它们通常又需要完整的集合扫描。我们已经完成了包括“计数”在内的“已覆盖查询”所能做的一切。
建议将原始详细信息子文档存储在由_id“链接”的单独集合中。除非在后台批处理期间(时间要求不高),否则永远不需要“查找联接”。更新非常罕见。
我们已经分析了由原始子文档组成的集合所占的比例,将它们移到一个单独的(且很少访问)的集合中将使平均文档大小减少3.5倍。
我们希望这将以相同的方式减少wiredTiger缓存大小的要求,从而减少我们的物理硬件RAM扩展要求。
问题是:由于CPU仅扫描轻得多的文档,因此在需要进行收集扫描时,我们还会看到查询执行时间的减少吗?此处的增益是否会近似于一个数量级,即〜3.5倍?
这是否是一个错误的希望,因为BSON结构允许wireTiger跳过每个文档中的所有“死木”。如果是这样的话,由于CPU高速缓存在高速缓存上,可能还会获得较小的收益吗?也就是说,较小的文档将在连续的内存中更多?
答案 0 :(得分:0)
现在已完成此收藏集的拆分。结果很好:
因此,如果由于子数组/文档较大,而您的集合(很多文档)的平均文档大小很大,并且查询很少需要这些子数组/文档(即,没有太多的$ lookup或类似),然后将它们分成一个单独的集合可能非常值得。
降低RAM需求并加快集合扫描速度,这大致是您设法减少平均文档大小的因素。