【问题标题】:How to avoid N+1 queries in Rails "each" loops?如何避免 Rails“每个”循环中的 N+1 个查询?
【发布时间】:2014-09-30 02:59:06
【问题描述】:

在一个待办事项列表样式的应用程序中,我有以下 ActiveRecord 模型方法:

class Task < ActiveRecord::Base
  # ...
  def project_name
    project.tasks.length > 0 ? "#{project.name} - #{name}" : project.name
  end
end

这个想法是在项目中有一项或多项任务时提供额外的项目信息。

但是,当在视图上定期调用时,这会产生性能问题(尤其是在数据集不断增长的情况下)。

优化此查询以使其在从视图中的“每个”循环调用时不会产生 N+1 查询类型问题的最佳方法是什么?

【问题讨论】:

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


    【解决方案1】:

    查看Eager Loading in the Rails guide。基本上你使用includes 方法一次加载所有任务,而不是N+1 方法。

    但是,对于您的示例,更好的方法是使用 counter caching。这会预先计算每个项目引用的任务数。通过将 project_name 逻辑放入 Task 类中,您还打破了关注点分离/“告诉,不要问”,它应该属于 Project 类:

    class Task
      def project_name
        project.name(self)
      end
    end
    
    
    class Project
      def name(task = nil) 
        return read_attribute[:name] if task.nil?
        tasks_count > 0 ? "#{read_attribute[:name]} - #{task.name}" : read_attribute[:name]
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多