Rails Active Record:如何减少到数据库的次数?

时间:2012-07-26 19:36:07

标签: sql ruby-on-rails-3 activerecord

在我的rails项目中,我有一项功能可以向用户显示他们的Facebook朋友是否已经在该网站上。在验证之后,我将他们的Facebook朋友加载到@fb_friends然后执行此操作:

  @fb_friends.each do |friend|
    friend_find = Authorization.find_by_uid_and_provider(friend[:identifier], 'facebook')
    if friend_find
      @fb_friends_on_cody << friend_find.user_id
      @fb_friends.delete(friend)
    end 
  end

基本上,如果找到匹配项(通过授权表),我会将该记录推送到@fb_friends_on_cody。这证明是一项非常昂贵的操作:

  1. 每位朋友都会点击一次数据库。所以在我的案例中总共执行了582个查询。

  2. 每个Authorization.find_by_uid_and_provider的性能都很差。我添加了一个像这样的索引:

    add_index "authorizations", ["uid", "provider"], :name => "index_authorizations_on_uid_and_provider", :unique => true
    
  3. 我想通过解决第一点可以看到很多性能提升。也许有一些方法可以使查询本身更有效。感谢这些方面的任何提示。

    解决方案

    使用Unixmonkey的指导,我能够将查询数量从582减少到1!这是最终的代码:

      friend_ids = @fb_friends.map{|f| f[:identifier] }
      authorizations = Authorization.where('provider = ? AND uid IN (?)','facebook',friend_ids)
      @fb_friends_on_cody = authorizations.map{ |a| { user_id: a.user_id, uid: a.uid }}
      @fb_friends.reject!{|f| @fb_friends_on_cody.map{|f| f[:uid]}.include?(f[:identifier]) } 
    

1 个答案:

答案 0 :(得分:2)

我认为这应该有用

friend_ids = @fb_friends.map(&:id)
authorizations = Authorization.where('provider = ? AND uid IN (?)','facebook',friend_ids)
@fb_friends_on_cody = authorizations.map(&:user_id)
@fb_friends.delete_all('id in (?)', @fb_friends_on_cody)