【问题标题】:Rails Active Record: How to reduce number of trips to database?Rails Active Record:如何减少访问数据库的次数?
【发布时间】:2012-07-26 19:36:06
【问题描述】:

在我的 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
    

我想通过解决第一点可以看到很多性能提升。也许有一些方法可以使查询本身更有效率。感谢您在这些方面的任何提示。

解决方案

在 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]) } 

【问题讨论】:

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


    【解决方案1】:

    我认为这应该可行

    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)
    

    【讨论】:

    • 谢谢!它不喜欢这条线@fb_friends.delete_all('identifier in (?)', @fb_friends_on_cody) 可能是因为@fb_friends 是一个数组(不是ActiveRecord)。我需要为数组找到类似的“delete_all”方法。
    • @fb_friends.reject!{|f| @fb_friends_on_cody.include?(f.id) }
    • 甜蜜。我发现了与delete_if 类似的东西。我实际上遇到了第一行@fb_friends.map(&amp;:id) 的问题,我之前已经在@fb_friends 上运行过mapsort,所以在拨打电话时基本上采用这种格式:[{:identifier=&gt;"520717406", :name=&gt;"Aaron Burr", :picture=&gt;"https://graph.facebook.com/520717406/picture"}... Running '@fb_friends.map (&:identifier)' 失败
    • @fb_friends.map{|f| f[:identifier] }
    • 谢谢!不得不进行一些调整,但让它启动并运行。这将查询数量(在我的情况下)从 582 减少到只有 4!我将添加最终代码作为问题的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多