新手问题 MongoDB 批量查询性能优化问题

mumuxizzz · October 11, 2017 · Last by mumuxizzz replied at October 12, 2017 · 5976 hits

项目中某行代码 ( map 迭代 ) 执行时占用 CPU 资源到 90% 多。 代码如下:

users = (uids.map {|uid| MasterFriend.find(uid)}).to_a

uids 是一个大小为 6000 多的数组,里面存放的 user 表的 id 字段(mongoid 自带的_id 字段)

这个迭代查询总耗时在 5s 以上,mongoid 默认_id 字段是加了索引的。MasterFriend 表不到 10000 条记录。

请教如何优化?👼


发现了新的问题,如上获得的 users 数组里面存放了很多个 document 对象(约为 5000)。然后我发现这种情况下,我去遍历这个数组,对每个 document 对象调用其 encode 方法(就是把输出为 json 格式),这个时候耗时更加严重。

def encode
  {
      id: self.id.to_s,
      images: images.first,
      gender: gender
  }
end

第一种遍历(严格意义上算不上遍历):

users.map :&encode

第二种遍历:

arr=[]
users.each do |u|
  arr << u.encode
end

发现第二种遍历方式比第一种执行速度要慢 1 倍。执行这两段代码的时候 cpu 都飙到 90% 多了。而且假如我直接把 users 数组赋值给另外一个数组,直接内存泄露了。🙁

我是一边在 rails console 中执行,一边开着另外一个窗口用 top 命令实时查看的。

请教一下,ruby 里面的迭代就这么耗时吗?数组存放太多数据是否也不合适?如何避免内存泄露的问题?

什么页面需要一下次取几千条数据出来?

😂 我想起来很久以前我也是不知道 where 和 find 可以直接传数组什么的 谷歌

Reply to ad583255925

是 API,倒是分页返回的。但是做法是先全部查到,然后分成很多份。需要第 x 页就返回第 x 份。不过这样倒提醒我了,我这样做是挺笨的,应该需要第多少页就查第几页数据。thanks

Reply to ad583255925

这个我知道的,但是不知道查询效率上会带来多少提升。我试一试。😇

为什么不一次取出?

Reply to nouse

没懂您的意思。我后来参照@gyorou的方法,这样执行查询:

users = MasterFriend.where(_id: { '$in': uids}).to_a

这样子比我最初的做法就快了很多。

  1. 就是上面你使用的,查询数据库的时候,可以直接传数组,没必要一条一条查。
  2. 分页可以直接用数据库做,不要全部查出来再分页吧。 比如下面的语句
"SELECT  `users`.* FROM `users` LIMIT 20 OFFSET 0"

在 ruby-china 这样和谐的社区,我觉得我变得平静了很多,看到这样的问题,我都能欣然接受了

类似

where id in (?)

已解决,改变了处理分页的逻辑。

mumuxizzz closed this topic. 12 Oct 16:38
You need to Sign in before reply, if you don't have an account, please Sign up first.