如何避免Rails的“每个”循环中的N + 1查询?
问题描述:
在待办事项列表式的应用程序,我有以下的ActiveRecord的模型方法:如何避免Rails的“每个”循环中的N + 1查询?
class Task < ActiveRecord::Base
# ...
def project_name
project.tasks.length > 0 ? "#{project.name} - #{name}" : project.name
end
end
的想法是提供更多的项目信息,如果有该项目的一个或多个任务。但是,当在视图上定期调用时,会产生性能问题(特别是在数据集不断增加的情况下)。
什么是优化此查询的最佳方式,以便在从视图中的“每个”循环调用时不会创建N + 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