我收藏了超过7000万份文件。每当我批量添加新文档时(比方说2K),插入操作非常慢。我怀疑是因为,mongo引擎正在将所有新文档的_id与所有7000万个文件进行比较,以找出任何_id重复条目。由于基于_id的索引是磁盘驻留的,因此它会使代码变慢。
无论如何都要避免这种情况。我只是想让mongo获取新文档并按原样插入,而不进行此检查。它甚至可能吗?
答案 0 :(得分:4)
您的问题包括一些关于MongoDB如何工作的主要假设。我将在下面解决这些问题,但我建议您尝试根据数据库指标(即serverStatus,mongostat,mongotop),系统资源等事实了解任何性能问题监视和MongoDB中的信息登录慢速查询。需要对指标进行长期监控,以便您可以确定部署的“正常”,因此我强烈建议使用MongoDB特定的监控工具,例如MMS Monitoring。
一些有趣的演示文稿为性能故障排除和调试提供了非常相关的背景材料:
除了了解实际性能挑战的位置和调整部署之外,您还可以通过以下方式提高插入效率:
删除此集合上任何未使用或冗余的二级索引
使用Bulk API批量插入文档
每当我批量添加新文档(比方说2K)时,插入操作非常慢。我怀疑是因为,mongo引擎正在将所有新文档的_id与所有7000万个文件进行比较,以找出任何_id重复条目。由于基于_id的索引是磁盘驻留的,因此它会使代码变慢。
如果一个集合有7000万个条目,那并不意味着索引查找涉及7000万个比较。索引值存储在B-trees中,这允许进行少量有效比较。确切的数字将取决于树的深度以及索引的构建方式和您正在查找的值......但是将在10s(而不是数百万)的比较顺序。
如果你真的好奇内部,有一些实验性存储&您可以在开发环境中启用的索引统计信息:Storage-viz: Storage Visualizers and Commands for MongoDB。
由于基于_id的索引是磁盘驻留的,因此它会使代码变慢。
MongoDB将您的working set(最近访问过的数据和索引条目的一部分)加载到可用内存中。
如果您能够以近乎升序的顺序创建id(例如,生成的ObjectIds),那么所有更新都将发生在B树的右侧,而您的工作集将会小得多(FAQ: "Must my working set fit in RAM")。
是的,我可以让mongo自己使用_id,但我不想浪费一个非常好的索引。而且,即使我让mongo为自己生成_id也不需要比较重复键错误吗?
MongoDB中的所有文档都需要唯一的_id
。默认ObjectId
是根据应确保唯一性的公式生成的(即返回重复键异常的可能性极低,因此您的应用程序不会获得重复的键异常,并且必须使用新的{{ 1}})。
如果您的文档中有唯一_id
的候选人,则可以随意使用此字段(或字段集合),而不是依赖生成的_id
。请注意,_id
是不可变的,因此您不应使用以后可能要修改的任何字段。