虽然我不知道在 MongoDB 中的确切技术原因,但我可以根据我对其他系统索引的了解以及您引用的文档对此做出一些假设。
索引的一般概念
当从一个文档移动到下一个文档时,在整个文档集合中,跳过所有不需要处理的数据会浪费大量时间和精力。如果您要查找 ID 为“1234”的文档,则必须遍历每个文档的 100K+ 会使其变慢
不必搜索集合中每个文档的所有内容(物理移动磁盘读取磁头等),索引可以加快速度。它基本上是一个键/值对,为您提供该文档的 id 和位置。 MongoDB 可以快速扫描索引中的所有 id,找到它需要的文档的位置,然后直接加载它们。
为索引分配文件大小
索引占用磁盘空间,因为它们基本上是存储在更小的位置的键/值对。如果您有一个非常大的集合(集合中有大量项目),那么您的索引会增大。
大多数操作系统以特定的块大小分配磁盘空间块。大多数数据库还根据需要以大块的形式分配磁盘空间。
当添加 100K 文档时,MongoDB 可能不会增长 100K 文件大小,而是可能会增长 1MB 或 10MB 之类的 - 我不知道实际增长的大小是多少。在 SQL Server 中,你可以告诉它增长的速度有多快,而 MongoDB 可能也有类似的东西。
分块增长能够更快地将文档“增长”到空间中,因为数据库不需要不断扩展。如果数据库现在已经分配了 10MB 的空间,它可以使用该空间。它不必为每个文档不断扩展文件。它只需要将数据写入文件。
这可能适用于集合和集合的索引——任何存储在磁盘上的东西。
文件大小和索引重建
当一个大集合添加和删除大量文档时,索引会变得碎片化。索引键可能不按顺序排列,因为索引文件中间有空间,而不是在最后需要构建索引时。索引键之间也可能有很多空间。
如果索引有10000条,需要插入#10001,则可能插入到索引文件的中间。现在索引需要重新构建以使一切恢复正常。这涉及移动大量数据,以便在文件末尾腾出空间并将第 10,001 项放在末尾。
如果索引不断被破坏 - 删除和添加了大量内容 - 增加索引文件大小并始终将内容放在末尾可能会更快。这样可以快速创建索引,但会在删除旧内容的文件中留下空洞。
如果索引文件在以前删除的地方有空白空间,则在读取索引时这是浪费精力。索引文件比需要的移动更多,以到达索引中的下一个项目。因此,索引会自行修复...对于非常大的集合或对集合进行非常大的更改可能会很耗时。
为大型索引文件重建
可能需要大量的磁盘访问和 I/O 操作才能正确地将索引文件压缩到合理的大小,并且一切都井井有条。将不合适的物品移到临时位置,在正确的位置释放空间,然后将它们移回。哦,顺便说一句,要释放空间,您必须将其他项目移动到临时位置。它是递归的和笨拙的。
因此,如果您的集合中有大量项目,并且该集合定期添加和删除项目,则可能需要从头开始重建索引。这样做会擦除当前的索引文件并从头开始重建——这可能比尝试在现有文件中进行数千次移动要快。它不是移动事物,而是从头开始按顺序编写它们。
集合大小的巨大变化
考虑到我上面的假设,集合大小的巨大变化会导致这种颠簸。如果您在集合中有 10,000 个文档并删除了其中的 8,000 个……那么,现在您的索引文件中有 8,000 个项目曾经所在的空白空间。 MongoDB 需要在物理文件中移动剩余的 2,000 个项目,以便以紧凑的形式重新构建它。
与其等待清理 8,000 个空白空间,不如用剩余的 2,000 个项目从头开始重建更快。
结论?也许?
因此,您引用的文档可能会处理“大数据”需求或高抖动集合和索引。
另外请记住,我是根据我对索引、磁盘分配、文件碎片等的了解做出有根据的猜测。
我的猜测是文档中的“大多数用户”,意味着 99.9% 或更多的 mongodb 集合不需要担心这一点。
MongoDB具体案例
根据 MongoDB 文档:
remove() 方法不会删除索引
因此,如果您从集合中删除文档,除非您为该集合重建索引,否则您会浪费磁盘空间。