拆分大文档
很常见的一种优化手段,在一些特定的业务场景中,会有一些很大的文档,这些文档有很多字段,而且有一些特定的字段还特别的大。可以考虑拆分这些文档
大文档对MongoDB的性能影响还是很大的,就我个人经验而言,认为可以考虑从两个角度出发拆分大文档:
- 按照字段的访问频率拆分: 访问频繁的放一个文档,访问不频繁的拆出去作为另一个文档
- 按照字段的大小来划分: 小字段放一个文档,大字段拆除去作为另外一个文档
之前拆分过一个文档,非常庞大。而且在业务中,有一些庞大的字段根本用不上,在这种情况下,一次拆除了三个文档。
- 访问频繁的小字段放在一起,作为一个文档
- 把访问不频繁的大字段拆出去作为一个文档。可以进一步优化为特定的巨大的字段可以直接作为一个文档
- 剩余的合并在一起作为一个文档
这样做的优点很明显,比较多的业务查询其实只需要第一种文档,极少数会需要第二种文档;但是缺点也很明显,如果调用者需要整个文档,也就意味着需要查询三次,再合并组成一个业务上完整的文档。
也可以升华一下:这种拆分终究是下策,最好还是在一开始使用MongoDB的时候就约束住文档的大小。
不过还有一个和这种策略完全相反的优化手段:嵌入文档
嵌入文档
如果A文档和B文档有关联关系,那么就在A文档里面嵌入B文档,做成一个大文档。
相当于原本A文档和B文档都是单独存储的,可能A文档里面有一个B文档的ID字段,又或者B文档里有A文档的ID字段,可以考虑合并这两个文档
可以这么介绍你的方案:
早期有一个过度设计的场景,就是有两个文档A和B,其中A里面有一个B的文档ID,建立了一对一的映射关系。但是实际上,业务查询的时候,基本上是分两次查询的,先把A查询出来,再根据A里面的文档ID也把B查出来。
后来这个地方慢慢成为了性能瓶颈,我就尝试优化了这个地方。我的想法是既然A和B在业务上联系那么紧密,我可以直接把他们整合成一个文档。整合之后,一次查询就能拿到所有需要的数据了,直接节约了一个MongoDB查询,提高了业务的响应时间,而且MongoDB的压力也变小了。