实施急切加载以停止 N+1 - Rails

Posted

技术标签:

【中文标题】实施急切加载以停止 N+1 - Rails【英文标题】:Implement eager loading to stop N+1 - Rails 【发布时间】:2017-09-14 17:32:48 【问题描述】:

我目前有一个页面需要 11 秒才能加载。我正在使用 Bullet Gem 来帮助我找到 N+1 查询发生的位置。它给了我一些输出,但我真的不知道该怎么做。这是 Bullet 的输出:

GET /events/1679/dashboard
USE eager loading detected
  RSVP => [:tickets]
  Add to your finder: :includes => [:tickets]
Call stack
  /Users/cameronbass/Desktop/Work/blackbird-rsvp/app/decorators/rsvp_decorator.rb:54:in `tickets?'
  /Users/cameronbass/Desktop/Work/blackbird-rsvp/app/views/accepted_rsvps/_list.html.erb:33:in `block in _app_views_accepted_rsvps__list_html_erb___1211423417683052584_70339569780320'

它告诉我把它放在这条线上

def tickets?
  rsvp.tickets.any?
end

这是关联:

has_many :tickets, through: :attendees

参加者.rb

has_one :ticket

【问题讨论】:

通常这是指迭代这些事物的列表并在每个事物上调用tickets?。该代码未显示,但大概您有一个列表...无论这些是什么。 查看您的日志!当您看到一个请求多次访问数据库时,您可能会遇到 N+1 的情况。您可以使用预先加载来代替只访问数据库一次以获取关联的表,然后加载记录。 当我看到这样的问题时,我觉得有必要链接到这个答案:***.com/a/26251892/525478。 YMMV 【参考方案1】:

Bullet 将您指向它检测到同一关联的多个调用的位置,指向您应该添加预加载的位置。

_list.html.erb 模板中的某处,您可能会遍历您的 RSVP(无论是什么),并且对于每个 RSVP,您试图通过调用 tickets 关联来确定它是否有任何票证。

Bullet 建议您将 include(:tickets) 添加到为您在模板中遍历的 RSVPs(可能在您的 AcceptedRSVPs 控制器中的某个位置)设置变量的查找器中。一旦完成,每个 RSVP 将不会运行 SQL 来查找其票证,因此您将摆脱 N+1 问题。

【讨论】:

以上是关于实施急切加载以停止 N+1 - Rails的主要内容,如果未能解决你的问题,请参考以下文章

Rails 急切加载

Rails 急切加载所有发现

使用 Rails 查询急切加载

在laravel [实现过滤器]中将多个表与雄辩和急切的加载一起加入

实施位置检查 Rails

Rails 中的 respond_to 出现未知格式错误。正确尝试实施轮询更新