【问题标题】:Optimizing Calculation in Rails在 Rails 中优化计算
【发布时间】:2015-07-07 14:51:55
【问题描述】:

我有三个模型,Property、Visit 和 Session。我需要计算一个属性的平均会话时间,到目前为止我有以下方法:

在我的会话模型中:

class Session < ActiveRecord::Base
  belongs_to :property
  has_many :visits

  def session_duration
    visits.last.created_at - visits.first.created_at
  end

end

然后在我的属性模型中:

class Property < ActiveRecord::Base

  has_many :visits
  has_many :sessions

  def avg_session_duration
    @sessions = Session.where(property_id: self.id)

    (@sessions.collect(&:session_duration).sum/@sessions.length)/60 if   @sessions.length > 0
  end
end

问题是,当我在具有数千个会话的属性上运行 avg_session_duration 时,计算花费的时间太长了,大约几分钟。我知道必须有一种更有效的方法来做到这一点。任何见解将不胜感激。

【问题讨论】:

  • 非规范化也值得研究。这意味着,您应该在会话行中有第一次和最后一次访问日期。当添加另一个访问时,更新上次会话缓存时间。这样,您将只需要查询会话。

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


【解决方案1】:

我猜这是因为N+1 queries problem:您正在为@sessions 集合中的每个项目查询visits。试试includes:

@sessions = Session.includes(:visits).where(property_id: self.id)

【讨论】:

  • 我相信它甚至会是一个带有 JOIN 的查询,不是吗?
  • 谢谢,使用 include 比我使用的要好得多!
  • @SergioTulentsev:实际上,当我在我的项目中使用has_many 运行includes 时,ActiveRecord 会构建两个查询。文档说使用includes 可能经常 结果在使用join 时,但根据我的卑微经验,只有当我使用referenceswhere 方法中关联表的引用条件强制它时,事情才会这样发展。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多