最近我注意到多次upserts(通过bulk operations)与插入(多个文档)之间存在巨大的性能差异。我想知道我是否正确:
find()
和update()
一样,它可以读取和写入2件事这样的性能差异?
如果是这种情况,我想知道我是否经常需要大量写入,而不是更新文档,我写了一个带有createdOn
字段的新文档。然后查询,我将只查询按createdOn DESC
排序的文档。我想知道这是一个好方法吗?或者,还有更好的方法?
答案 0 :(得分:18)
如果插入文档,Mongodb需要检查具有相同objectId的文档是否存在。如果其存在的文件无法插入。
同样的情况适用于更新。它需要检查文档是否存在。其他更新无法执行。如果您未根据ObjectId / Indexed字段查找文档,则更新查询将变慢的情况。
插入/更新文档的其他性能应该相同。
例如.....
所以插入可以像这样//(快速)
使用upsert更新(ObjectId可用)//(快速)
或者使用upsert更新(没有ObjectId)//这很慢
答案 1 :(得分:2)
我没有找到关于upsert
如何在MongoDB中工作的'官方'解释,但是可以安全地假设,因为该操作旨在更新现有文档并且仅在添加文档时无法找到具有给定标准的文档。
如果添加索引,则{{1}}可以变得更快:在所有索引用于“查找”文档之后。需要注意的是索引操作的字段以及您要更新的字段。如果更新的部分是索引的一部分,则会对更新文档产生性能影响。如果更新的部分不是索引的一部分,则不会因在现有文档中写入而受到处罚。如果添加了文档,则会对性能产生轻微影响,因为索引集合已更新。但仍然是:只需添加文档就会更快。
因此,如果在您的方案中您知道您不想更新文档,那么插入通常会更快。如果要确保两次不添加同一文档,还可以选择添加唯一索引。然后插入就会失败。
总而言之,这取决于具体的情况,但根据我可以从您的问题中提取的信息,我认为最好的选择是简单地插入文档。由于您似乎确保'createdon'字段使文档中的文档唯一,因此您只需担心读取方案中使用的索引。
可在MongoDB网站上找到一些额外信息:
有关设计(读取)索引的更多信息,可以找到关于查找索引是否向查询计划添加任何内容的非常好的解释here:
我希望这会有所帮助。