优化计算建议并与多对多关系一起工作

时间:2011-06-15 18:08:37

标签: ruby-on-rails ruby optimization performance

我有两个模型UserBrand,以及它们之间的多对多关系(通过UserBrand表)。我有大约一千个用户,一千个品牌和每个用户最喜欢的一百个品牌。

User.all.count # => 1000
Brand.all.count # => 1000
User.find(1).brands # => 100

如果我想找到5个用户,哪些喜欢的品牌几乎等同于当前用户',我在用户模型中写了以下内容

class User < ActiveRecord::Base
  has_many :user_brands
  has_many :brands, :through => :user_brands

  def similar_users
    result = {}

    User.all.each do |u|
        result[u] = shared_brands_with u.brands
    end

    result.sort{ |a, b| b[1] <=> a[1] }[1..5].map!{ |e| e[0] }
  end

  def shared_brands_with(brands)
    (brands & @brands).size
  end
end

以及users/show视图中的以下内容

<h2>Similar users</h2>
<ul>
  <% @user.similar_users.each do |user| %>
    <li><%= link_to user.name, user %></li>
  <% end %>
</ul>

但是在浏览器中查看用户建议大约需要30-60秒。

所以我的问题是“如何加快推荐计算?”

UPD:使用

    User.includes(:brands).each do |u|
        result[u] = shared_brands_with u.brands
    end

性能翻倍,但即使有50个品牌而不是100个品牌,在10秒内提供推荐也非常缓慢。

1 个答案:

答案 0 :(得分:0)

所以,基本上。你正在拉动整个用户表。对于每个人,抓住该用户的品牌列表,大概是品牌本身。并过滤。我不会认为它很快。 : - )

您需要在SQL中重写该逻辑以使其快速。对不起,我不会比红宝石更流畅 - 不能真正理解标准......但实质上,通过一个查询获取品牌。

它会变得庞大而丑陋,充满了联接和()以及可能分组/有条款,但它会比你当前的方法更快。