jav*_*ezg 20 theory indexing fragmentation mongodb
与MongoDB合作了一段时间,今天我在与同事讨论时遇到了疑问.
问题是,当您在MongoDB中创建索引时,将处理该集合并构建索引.
索引在文档的插入和删除过程中更新,因此我并不真正看到需要运行重建索引操作(删除索引然后重建它).
根据MongoDB文档:
通常,MongoDB在例程更新期间压缩索引.对于大多数用户,不需要reIndex命令.但是,如果集合大小发生了显着变化,或者索引消耗了不成比例的磁盘空间,则可能值得运行.
有人需要运行值得的重建索引操作吗?
Ste*_*nie 11
根据MongoDB文档,通常不需要定期重建索引.
注意:MongoDB 3.0+引入了可插拔存储引擎API,对存储的任何建议都会变得更加有趣.我在下面的评论是专门参考MongoDB 3.0及更早版本中的默认MMAP存储引擎.WiredTiger和其他存储引擎具有不同的数据和索引存储实现.
在以下情况下,使用MMAP存储引擎重建索引可能会有一些好处:
与数据相比,索引消耗的空间量大于预期.注意:您需要监视历史数据和索引大小以获得用于比较的基准.
您希望从较旧的索引格式迁移到较新的索引格式.如果建议使用reindex,则会在升级说明中提及.例如,MongoDB 2.0引入了显着的索引性能改进,因此发行说明包括升级后建议的v2.0格式重新索引.类似地,MongoDB 2.6引入了2dsphere(v2.0)具有不同默认行为的索引(默认为稀疏).索引版本升级后不会重建现有索引; 是否/何时升级的选择由数据库管理员决定.
您已将_id集合的格式更改为单调递增键(例如ObjectID)或从随机值更改为随机值.这有点深奥,但如果你要插入_id总是在增加的s(ref:SERVER-983),那么有一个索引优化可以分割b-tree桶90/10(而不是50/50 ).如果您的_ids 的性质发生显着变化,则可以构建具有重新索引的更高效的b树.
有关一般B树行为的更多信息,请参阅:Wikipedia:B-tree
如果你真的很想进一步深入研究索引内部,你可以尝试一些实验性的命令/工具.我希望它们仅限于MongoDB 2.4和2.6:
虽然我不知道为什么在 MongoDB 中的确切技术原因,但我可以根据我对其他系统索引的了解以及您引用的文档,对此做出一些假设。
当从一个文档移动到下一个文档时,在整个文档集合中,跳过所有不需要处理的数据会浪费大量时间和精力。如果您要查找 ID 为“1234”的文档,则必须遍历每个文档的 100K+ 使其变慢
不必搜索集合中每个文档的所有内容(物理移动磁盘读取磁头等),索引可以加快速度。它基本上是一个键/值对,为您提供该文档的 id 和位置。MongoDB 可以快速扫描索引中的所有 id,找到它需要的文档的位置,然后直接加载它们。
索引占用磁盘空间,因为它们基本上是存储在更小的位置的键/值对。如果您有一个非常大的集合(集合中有大量项目),那么您的索引会增大。
大多数操作系统以特定的块大小分配磁盘空间块。大多数数据库还会根据需要以大块的形式分配磁盘空间。
当添加 100K 的文档时,MongoDB 不会增加 100K 的文件大小,而是可能会增长 1MB 或 10MB 之类的 - 我不知道实际的增长大小是多少。在 SQL Server 中,你可以告诉它增长的速度有多快,而 MongoDB 可能有类似的东西。
分块增长可以更快地将文档“增长”到空间中,因为数据库不需要不断扩展。如果数据库现在已经分配了 10MB 的空间,它可以只使用该空间。它不必为每个文档不断扩展文件。它只需要将数据写入文件。
这可能适用于集合和集合索引——任何存储在磁盘上的东西。
当大型集合添加和删除了大量文档时,索引会变得碎片化。索引键可能不按顺序排列,因为当需要构建索引时,索引文件的中间而不是末尾有空间。索引键之间也可能有很多空间。
如果索引中有10,000个项目,并且需要插入#10,001,则可能会插入到索引文件的中间。现在索引需要重新构建自己以将所有内容放回原处。这涉及移动大量数据,以在文件末尾腾出空间并将项目 # 10,001 放在末尾。
如果索引不断被破坏 - 删除和添加了大量内容 - 增加索引文件大小并始终将内容放在最后可能会更快。这可以快速创建索引,但会在删除旧内容的文件中留下空洞。
如果索引文件在以前删除的东西有空的空间,那么在读取索引时这是浪费精力。索引文件的移动量超出了需要,以到达索引中的下一项。因此,索引会自行修复……对于非常大的集合或对集合进行非常大的更改,这可能会很耗时。
可能需要大量的磁盘访问和 I/O 操作才能将索引文件正确压缩回合理的大小,并且一切正常。将不合适的物品移到临时位置,在正确的位置释放空间,然后将它们移回。哦,顺便说一句,要释放空间,您必须将其他项目移动到临时位置。它是递归的和严厉的。
因此,如果您在一个集合中有大量项目并且该集合定期添加和删除项目,则可能需要从头开始重建索引。这样做会擦除当前的索引文件并从头开始重建——这可能比尝试在现有文件内进行数千次移动要快。它不是移动事物,而是从头开始按顺序写入它们。
给出我在上面假设的所有内容,集合大小的巨大变化会导致这种颠簸。如果您在集合中有 10,000 个文档并且您删除了其中的 8,000 个……那么,现在您的索引文件中有 8,000 个项目的空白空间。MongoDB 需要移动物理文件中剩余的 2,000 个项目,以紧凑的形式重建它。
与其等待 8,000 个空闲空间被清理干净,不如用剩余的 2,000 个项目从头开始重建会更快。
因此,您引用的文档可能会处理“大数据”需求或高抖动集合和索引。
还要记住,我是根据我对索引、磁盘分配、文件碎片等的了解做出有根据的猜测。
我的猜测是文档中的“大多数用户”,意味着 99.9% 或更多的 mongodb 集合不需要担心这个。
根据 MongoDB 文档:
remove() 方法不会删除索引
因此,如果您从集合中删除文档,您就是在浪费磁盘空间,除非您为该集合重建索引。
| 归档时间: |
|
| 查看次数: |
13034 次 |
| 最近记录: |