Ruby Mongoid各+;设置与标准#设置与更新#所有+$addToSet

Ruby Mongoid各+;设置与标准#设置与更新#所有+$addToSet,ruby,mongodb,mongoid,Ruby,Mongodb,Mongoid,我想知道什么性能/内存方面更好:迭代集合中的所有对象并调用set/add_to_set,或者直接在条件上调用set/add_to_set,或者使用updateall with set/add_to_set # update_all User.where(some_query).update_all( { '$addToSet': { :'some.field.value' => :value_to_add } } ) # each do + add_t

我想知道什么性能/内存方面更好:迭代集合中的所有对象并调用set/add_to_set,或者直接在条件上调用set/add_to_set,或者使用updateall with set/add_to_set

# update_all
User.where(some_query).update_all(
  {
    '$addToSet': {
      :'some.field.value' => :value_to_add
    }
  }
)

# each do + add_to_set
User.where(some_query).each do |user|
  user.add_to_set(:'some.field.value' => :value_to_add)
end

# Criteria#add_to_set
User.where(some_query).add_to_set(
  :'some.field.value' => :value_to_add
)

欢迎您的任何意见。谢谢

我用verbose标志启动了MongoDB服务器。这就是我得到的

备选案文1。更新选择器上应用的所有

2017-04-25 COMMAND command production_v3.$cmd command: update { update: "products", updates: [ { q: { ... }, u: { $addToSet: { test_field: "value_to_add" } }, multi: true, upsert: false } ], ordered: true }
我删除了一些输出,以便更容易阅读。流程是:

  • MongoID生成指定查询和更新的单个命令
  • MongoDB服务器获取该命令。它一次完成收集并更新每个匹配项
注意!您可以从源代码中学习,也可以视为理所当然。因为按照我的术语,MongoID在步骤1中生成要发送的命令,所以它不会检查您的模型。e、 g.如果'some.field.value'不是模型用户中的字段之一,则该命令仍将执行并在数据库中持久化

备选案文2。每个都在选择器上

我得到如下find命令,后跟多个getMore-s:

2017-04-25 COMMAND command production_v3.products command: find { find: "products", filter: { ... } } 0ms
我还收到了大量的更新:

2017-04-25 COMMAND command production_v3.$cmd command: update { update: "products", updates: [ { q: { _id: ObjectId('52a6db196c3f4f422500f255') }, u: { $addToSet: { test_field: { $each: [ "value_to_add" ] } } }, multi: false, upsert: false } ], ordered: true } 0ms
该流程与第一个选项完全不同:

  • MongoID向MongoDB服务器发送一个简单查询。如果您的集合足够大,并且查询覆盖了其中的一个重要部分,则在循环中会发生以下情况:
  • [循环]使用所有匹配项的子集进行响应。剩下的留给下一次迭代
  • [loop]MongoID以哈希格式获取匹配项的数组。MongoID解析每个条目并为其初始化用户类。那是一个昂贵的手术
  • [loop]对于上一步中的每个用户实例,MongoID生成更新命令并将其发送到SERVICE。插座也很贵
  • [loop]MongoDB获取命令并遍历集合,直到第一次匹配为止。更新匹配。它很快,但在一个循环中累积一次
  • [loop]MongoID解析响应并相应地更新其用户实例。昂贵且不必要
备选案文3。将_添加到应用于选择器的_集合

在发动机罩下,它相当于选项1。就这个问题而言,它的CPU和内存开销无关紧要

结语

选项2的速度慢得多,因此基准测试毫无意义。在我尝试的特定案例中,它导致了对MongoDB的1000次请求和1000次用户类初始化。选项1和3导致对MongoDB的单个请求,并依赖于MongoDB高度优化的引擎