2013-01-15 47 views
85

每猫鼬documentationMongooseJSMongoDB/Node.js猫鼬索引在生产代码

当你的应用程序启动后,猫鼬自动模式中的每个定义的索引调用ensureIndex。尽管开发很好,但建议在生产中禁用此行为,因为索引创建可能会对性能产生重大影响。将架构的autoIndex选项设置为false来禁用此行为。

这似乎是指示在部署之前从猫鼬中删除自动索引以优化Mongoose,从而指示Mongo在应用程序启动时通过所有索引进行转移和转移,这似乎是有意义的。

在生产代码中处理索引的正确方法是什么?也许外部脚本应该生成索引?或者,如果单个应用程序是集合的唯一读取器/写入器,那么可能不需要ensureIndex,因为每次发生数据库写入时它都会继续索引?

编辑:为补充,MongoDB中提供了良好的documentation如何做索引,但不为什么明确索引指令应该做的。在我看来,索引应该由编写器应用程序自动保持在具有现有索引的集合上,并且ensureIndex实际上更多的是一次性的事情(当新索引被应用时完成),在这种情况下,Mongoose的autoIndex应该在正常的服务器重新启动下无法运行。

+10

无论谁低估了这个问题,请提供一个理由。 – rdrey

回答

90

我从来没有理解为什么Mongoose文档如此广泛地推荐在生产中禁用autoIndex。一旦添加了索引,后续的ensureIndex调用将只会看到索引已经存在,然后返回。所以当你第一次创建索引时,它只会对性能产生影响,并且在那个时候集合通常是空的,因此无论如何创建索引都会很快。

我的建议是让autoIndex启用,除非你有一个特定的情况,它给你的麻烦;就像如果你想添加一个新的索引到一个拥有数百万个文档的现有集合,并且你想更多地控制它的创建时间。

+4

我有一个问题要添加...如果我将它设置为假,该怎么办?当我插入数据或者我需要明确地创建它时,会创建索引。如果这是一个新手问题,我很抱歉,但如果你回答的话,它会非常有帮助。 –

+3

@SaranshMohapatra当'autoIndex'为false时,您需要在模型上调用[ensureIndexes](http://mongoosejs.com/docs/api.html#model_Model.ensureIndexes)来创建索引。 – JohnnyHK

+0

比我每次都需要调用它还是只需定义一次模型? –

28

虽然我接受的答案一致,其值得注意的是,根据MongoDB manual,这是不是在生产服务器上增加索引的推荐方式:

如果您的应用程序包括ensureIndex()操作并且其他操作问题不存在索引,构建索引可能会严重影响数据库的性能。

要避免性能问题,请确保您的应用程序在启动时使用getIndexes()方法或驱动程序的等效方法检查索引,并在适当索引不存在时终止。在指定维护时段内,始终使用不同的应用程序代码在生产实例中构建索引

当然,这取决于您的应用程序的结构和部署方式。例如,如果您正在部署到Heroku,并且您没有使用Heroku的preboot feature,那么很可能您的应用程序在启动过程中根本没有提供请求,因此当时创建索引可能很安全。

除此之外,从公认的答案:

因此,只有当你第一次创建索引,和当时的藏品往往空的,所以创建索引对性能的影响反正很快。

如果你已经设法在第一时间确定你的数据模型和查询,这很好,而且经常是这样。但是,如果您要向应用程序添加新功能,并且在没有索引的属性上使用新的数据库查询,则通常会向包含许多现有文档的集合添加索引。

这是您需要小心添加索引的时候,并仔细考虑这样做的性能影响。例如,您可以create the index in the background

db.ensureIndex({ name: 1 }, { background: true }); 
+3

好的,所以你所要做的就是不启动你的服务器,直到所有的ensureIndex回调为每个集合触发。 –

+0

@AlexMills你如何确保? – lonelymo

+0

async.each(Object.keys(models),function(key,cb){[key] .ensureIndexes(cb) },cb) –