0

我有以下 ActiveRecord 查询。在我的测试环境中消息数为 50 时运行良好,但当我们投入生产时,消息数增长到 5000 条时,响应时间接近 30 秒。不好。

我怎样才能更有效地进行此查询,因此随着消息数量的增加保持快速。如果尚未完成,查询会从所有消息中查找所有警报。

class AlertsController < ApplicationController
  before_filter :get_user
  respond_to :json, :html

 def index
    @messages = current_user.messages.where(:active => true).order("created_at ASC")

    @alerts = Array.new
    @messages.each do |message|
        if (message.alerts.count > 0)
          @alerts = @alerts + message.alerts.where(:completed => false)
        end
    end

    respond_to do |format|
      format.html
      format.json
    end
  end

end


class Alert < ActiveRecord::Base
    belongs_to :message

class Message < ActiveRecord::Base
  has_many :alerts, dependent: :destroy
4

2 回答 2

3

根据 Jesse 的回答,更好的方法是创建一个仅选择 的范围pending_alerts,这样您可以传递更少的数据,并让数据库完成更多的工作。

class Message < ActiveRecord::Base
  scope :pending_alerts, lambda {
    alerts.where(:completed => false)
  }
}

然后在控制器中:

@messages = current_user.messages.includes(:pending_alerts).where(:active => true).order("created_at ASC")  
@alerts = @messages.map { |m| m.alerts } 
于 2012-06-27T14:20:49.200 回答
1

这似乎是一个 n+1 问题。此处的文档(搜索N + 1 个查询问题的解决方案

@messages = current_user.messages.includes(:alerts).where(:active => true).order("created_at ASC")

然后使@alerts 更简单:

@alerts = @messages.map do |message|
  message.alerts.select {|alert| !alert.completed}
end
于 2012-06-27T14:08:15.400 回答