【问题标题】:Mongoose indexing in production code生产代码中的猫鼬索引
【发布时间】:2012-12-29 20:16:59
【问题描述】:

对于 MongooseJSMongoDB/Node.js 的猫鼬 documentation

当您的应用程序启动时,Mongoose 会自动为您架构中定义的每个索引调用ensureIndex。虽然很适合开发,但建议在生产中禁用此行为,因为创建索引会导致显着的性能影响。通过将架构的 autoIndex 选项设置为 false 来禁用该行为。

这似乎指示在部署之前从 mongoose 中删除自动索引,以优化 Mongoose,使其不再指示 Mongo 在应用程序启动时遍历所有索引,这似乎是有道理的。

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

编辑:作为补充,MongoDB 提供了很好的documentation 用于如何 进行索引,但没有为什么何时 应该使用明确的索引指令。在我看来,索引应该由编写器应用程序自动在具有现有索引的集合上保持最新,ensureIndex 实际上更像是一次性的事情(在应用新索引时完成),在这种情况下 Mongoose 的autoIndex 应该是正常服务器重启下的空操作。

【问题讨论】:

  • 最好使用单独的脚本进行索引,该脚本不会在每次部署时都执行。更多的是从维护的角度来看。否则,某些开发人员有一天会为已经拥有数百万条记录的集合添加一些索引,然后可能会导致重大业务损失。

标签: node.js mongodb mongoose


【解决方案1】:

使用此块代码处理生产模式:

const autoIndex = process.env.NODE_ENV !== 'production';
mongoose.connect('mongodb://localhost/collection', { autoIndex });

【讨论】:

  • 错误答案。如果这样做,您的生产服务器将永远不会有任何索引!
【解决方案2】:

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

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

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

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

除此之外,从接受的答案:

所以它只会在您第一次创建索引时对性能产生影响,而那时集合通常是空的,因此无论如何创建索引都会很快。

如果您第一次就成功地确定了您的数据模型和查询,这很好,而且经常如此。但是,如果您要向应用添加新功能,并在没有索引的属性上使用新的数据库查询,您通常会发现自己向包含许多现有文档的集合添加索引。

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

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

【讨论】:

  • 好的,所以您要做的就是在为每个集合触发所有 ensureIndex 回调之前不要启动服务器。
  • @AlexMills 你如何确保这一点?
  • async.each(Object.keys(models), function (key, cb) { models[key].ensureIndexes(cb) }, cb)
  • 没有ensureIndex了。取而代之的是createIndex。我说的对吗?
  • 背景现已弃用。 Mongodb 将从 4.2 开始忽略它。 Mongodb 现在将使用专门的异步构建进行索引构建,除了在文档docs.mongodb.com/manual/reference/method/… 中指定的构建过程的开始和结束期间
【解决方案3】:

我一直不明白为什么 Mongoose 文档如此广泛地建议在生产中禁用 autoIndex。添加索引后,后续的ensureIndex 调用将简单地看到索引已经存在,然后返回。所以它只会在你第一次创建索引时对性能产生影响,那时集合通常是空的,所以无论如何创建索引都会很快。

我的建议是让autoIndex 保持启用状态,除非您遇到特定情况给您带来麻烦;例如,如果您想向拥有数百万个文档的现有集合添加新索引,并且希望更好地控制它的创建时间。

【讨论】:

  • 我有一个问题要补充...如果我将其设置为 false 怎么办?当我插入数据或者我需要显式创建它时,将创建索引。如果这是一个新手问题,我很抱歉,但如果你能回答这将非常有帮助。
  • @SaranshMohapatra 当autoIndex 为假时,您需要在模型上调用ensureIndexes 以创建其索引。
  • 我必须每次都调用它还是只定义模型一次?
  • @SaranshMohapatra 定义(编译)模型时。当我第一次启动应用程序时,我会这样做。现在很难考虑的是决定删除所有索引并重新创建它们,以防架构更改。
  • @JohnnyHK 现在都快 2016 年了,你还同意你的回答吗?
猜你喜欢
  • 2014-06-21
  • 2017-01-26
  • 2018-01-10
  • 2017-09-04
  • 2020-10-03
  • 2016-10-29
  • 1970-01-01
相关资源
最近更新 更多