实施急切加载以停止 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的主要内容,如果未能解决你的问题,请参考以下文章