MongoDB:Update / Upsert vs Insert

时间:2016-01-31 10:34:35

标签: mongodb mongodb-query upsert

最近我注意到多次upserts(通过bulk operations)与插入(多个文档)之间存在巨大的性能差异。我想知道我是否正确:

  • Upsert / Updates就像find()update()一样,它可以读取和写入2件事
  • 插入只会写得更快

这样的性能差异?

如果是这种情况,我想知道我是否经常需要大量写入,而不是更新文档,我写了一个带有createdOn字段的新文档。然后查询,我将只查询按createdOn DESC排序的文档。我想知道这是一个好方法吗?或者,还有更好的方法?

  • 我想知道我是否有关于该集合的索引,是否可以加快更新速度?但是这个索引不会减慢写入部分吗?
  • 使用第二种方式,我只进行插入,它会慢下来然后我有太多文件吗?它是否实用(加快写入速度)?
  • 我也尝试过增加连接池大小。不确定什么是最佳的,但我试过20,我看到我可以通过mongostat处理每秒20次查询。我预计它会更高。

2 个答案:

答案 0 :(得分:18)

如果插入文档,Mongodb需要检查具有相同objectId的文档是否存在。如果其存在的文件无法插入。

同样的情况适用于更新。它需要检查文档是否存在。其他更新无法执行。如果您未根据ObjectId / Indexed字段查找文档,则更新查询将变慢的情况。

插入/更新文档的其他性能应该相同。

例如.....

所以插入可以像这样//(快速)

  1. (检查文档 - >未找到 - >插入新文档)其他
  2. (检查文档 - >找到 - >无法插入)
  3. 使用upsert更新(ObjectId可用)//(快速)

    1. (检查文档 - >未找到 - >插入新文档)其他
    2. (检查文档 - >找到 - >更新文档)
    3. 或者使用upsert更新(没有ObjectId)//这很慢

      1. (查找ObjectId(慢) - >未找到 - >插入新文档)其他
      2. (查找ObjectId(慢) - >找到 - >更新文档)

答案 1 :(得分:2)

我没有找到关于upsert如何在MongoDB中工作的'官方'解释,但是可以安全地假设,因为该操作旨在更新现有文档并且仅在添加文档时无法找到具有给定标准的文档。

如果添加索引,则{{1}}可以变得更快:在所有索引用于“查找”文档之后。需要注意的是索引操作的字段以及您要更新的字段。如果更新的部分是索引的一部分,则会对更新文档产生性能影响。如果更新的部分不是索引的一部分,则不会因在现有文档中写入而受到处罚。如果添加了文档,则会对性能产生轻微影响,因为索引集合已更新。但仍然是:只需添加文档就会更快。

因此,如果在您的方案中您知道您不想更新文档,那么插入通常会更快。如果要确保两次不添加同一文档,还可以选择添加唯一索引。然后插入就会失败。

总而言之,这取决于具体的情况,但根据我可以从您的问题中提取的信息,我认为最好的选择是简单地插入文档。由于您似乎确保'createdon'字段使文档中的文档唯一,因此您只需担心读取方案中使用的索引。

可在MongoDB网站上找到一些额外信息:

有关设计(读取)索引的更多信息,可以找到关于查找索引是否向查询计划添加任何内容的非常好的解释here

我希望这会有所帮助。