在我的 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。这被证明是一个非常昂贵的操作:
每个朋友都会访问数据库一次。所以在我的例子中,总共执行了 582 个查询。
每个 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]) }