我有一个跟踪订阅订单邮件的 Rails 3.2 应用程序。
基本模型结构为:
订购 has_many 订阅 has_many SubscriptionMailings
每个月都会为每个订阅邮件生成一条记录,并从这些记录中导出一个 csv 文件。
邮寄地址存储在订单级别。
基本上,我选择了当月有效的所有订阅,并循环通过它们从订单对象中获取邮寄地址。然后我为每一个创建一个新的订阅邮件记录。
现在这工作正常,因为没有很多订阅,但它很慢。
我怎样才能加快这个过程?
我有一个跟踪订阅订单邮件的 Rails 3.2 应用程序。
基本模型结构为:
订购 has_many 订阅 has_many SubscriptionMailings
每个月都会为每个订阅邮件生成一条记录,并从这些记录中导出一个 csv 文件。
邮寄地址存储在订单级别。
基本上,我选择了当月有效的所有订阅,并循环通过它们从订单对象中获取邮寄地址。然后我为每一个创建一个新的订阅邮件记录。
现在这工作正常,因为没有很多订阅,但它很慢。
我怎样才能加快这个过程?
为了进行优化,您需要从 Ruby 级别降级到这里的 SQL 级别。
而不是进行N+1
选择(1
用于获取所有订阅和N
获取每个订阅的所有订单),您可能只能1
使用连接进行选择。
SubscriptionMailing.
joins(:subscrtiption).
joins(:order).
where(Order.table_name => { valid: true })
听起来您想使用包含来急切加载订单。也许是这样的:
# Subscription.rb
scope :valid_for_month lambda {|month| where(month: month)}
# Elsewhere
valid_subscriptions = Subscription.valid_for_month(Time.now.month).includes(:order)
valid_subscriptions.each do |subscription|
subscription.generate_subscription_mailing
end
更多内容包括:http ://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
经过一番研究,我最终将我的代码包装在一个事务中,而没有进行任何其他更改。
它加快了速度。
在我添加事务之前,代码需要 1 多分钟才能运行,现在它减少到大约 10 秒。这对我的需求来说已经足够快了,所以我没有尝试进一步优化。
ActiveRecord::Base.transaction do
# my db stuff here
end