渴望加载N + 1期

时间:2012-06-13 20:11:29

标签: ruby-on-rails ruby-on-rails-3 postgresql eager-loading

 <%- @lessons.includes(:bookmarks).each_with_index do |lesson, index| -%>
          <tr>
            <td class="w6 pl">
              <%- bookmark = lesson.bookmarks.where(user_id: current_user).first -%>
              <%= render :partial => "student/lessons/bookmark", :locals => {:bookmark => bookmark, :lesson => lesson} %>
            </td>
          </tr>
 <%- end -%>

以上代码产生以下N + 1个查询:

  Bookmark Load (0.3ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" IN (1, 2, 3, 4, 5, 6)
  Bookmark Load (0.3ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 1 AND "bookmarks"."user_id" = 1 LIMIT 1
Rendered student/lessons/_bookmark.html.erb (1.4ms)
  Bookmark Load (0.3ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 2 AND "bookmarks"."user_id" = 1 LIMIT 1
Rendered student/lessons/_bookmark.html.erb (0.6ms)
  Bookmark Load (0.3ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 3 AND "bookmarks"."user_id" = 1 LIMIT 1
Rendered student/lessons/_bookmark.html.erb (0.6ms)
  Bookmark Load (0.3ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 4 AND "bookmarks"."user_id" = 1 LIMIT 1
Rendered student/lessons/_bookmark.html.erb (0.6ms)
  Bookmark Load (0.2ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 5 AND "bookmarks"."user_id" = 1 LIMIT 1
Rendered student/lessons/_bookmark.html.erb (0.6ms)
  Bookmark Load (0.1ms)  SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."lesson_id" = 6 AND "bookmarks"."user_id" = 1 LIMIT 1

如何在第一个之后阻止额外的查询,因为我在循环中使用where查询?

谢谢!

1 个答案:

答案 0 :(得分:2)

您需要手动执行两个查询:

@lessons = Lesson.all # i.e.
@bookmarks = Bookmark.select("bookmarks.*, DISTINCT(lesson_id)").where(user_id: current_user.id)

然后

@lessons.each do |lesson|
  ...
  bookmark = @bookmarks.detect{ |b| b.lesson_id == lesson.id }
  ...
end