【问题标题】:Rails ActiveRecord Performance with many Selects and InsertsRails ActiveRecord 性能与许多选择和插入
【发布时间】:2012-05-26 05:51:18
【问题描述】:

我有一个 Rails 3.2 应用程序,用于跟踪订阅订单的邮件。

基本模型结构是:

订购 has_many Subscriptions has_many SubscriptionMailings

每个月都会为每个订阅邮件生成一条记录,并从这些记录中导出一个 csv 文件。

邮寄地址存储在订单级别。

基本上,我会选择当月有效的所有订阅,然后循环遍历它们,从订单对象中获取邮寄地址。然后我为每一个创建一个新的订阅邮件记录。

现在这可以正常工作,因为订阅量不多,但速度很慢。

我怎样才能加快这个过程?

【问题讨论】:

  • 您能否发布一个日志摘录,向我们展示查询及其持续时间?还是纯粹的数据库操作需要这么长时间,还是还有一些应用程序级的逻辑在起作用(回调、观察者或复杂的验证)?

标签: ruby-on-rails ruby-on-rails-3 performance activerecord


【解决方案1】:

为了优化,这里需要从Ruby级别降到SQL级别。

除了N+1 选择(1 用于获取所有订阅,N 用于获取每个订阅的所有订单)之外,您可能只能使用 1 选择连接。

SubscriptionMailing.
  joins(:subscrtiption).
  joins(:order).
  where(Order.table_name => { valid: true })

【讨论】:

    【解决方案2】:

    听起来您想使用包含来急切加载订单。也许是这样的:

    # 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

    【讨论】:

      【解决方案3】:

      经过一些研究,我最终将我的代码包装在一个事务中,而没有进行任何其他更改。

      它加快了速度。

      在我添加事务之前,代码运行需要超过 1 分钟,现在已降至大约 10 秒。这对我的需求来说已经足够快了,所以我没有尝试进一步优化。

      ActiveRecord::Base.transaction do
         # my db stuff here
      end
      

      【讨论】:

        猜你喜欢
        • 2021-06-14
        • 1970-01-01
        • 1970-01-01
        • 2012-11-08
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2012-09-03
        • 2011-10-20
        相关资源
        最近更新 更多