我有以下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
答案 0 :(得分:3)
建立Jesse的答案,更好一点就是创建一个范围来只选择pending_alerts
,这样你就可以传递更少的数据,并让数据库完成更多的工作。 / p>
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 }
答案 1 :(得分:1)
这似乎是一个n + 1问题。这里的文档(搜索Solution to N + 1 queries problem)
@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