#目次
①N+1問題とは
②具体例
③解決方法
##①N+1問題とは
データベースからデータを取り出す際に、必要以上にSQLが発行され動作が悪くなってしまう問題のことをいう。
##②具体例
例えば、Userがcommentを投稿するwebアプリがあるとする。ここで、複数のUserが投稿したcommentを全権取得する場合、ユーザーのnickenameを表示させることをしたいケースを考える。
class CommentsController < ApplicationController
def index
@comments = Comment.all
end
end
#コメントを全件取得している
<% @comments.each do |comment| %>
<%= comment %>
<small><%= comment.user.nickname %></small>
<%end%>
#一つ一つのコメントに対してのユーザーのニックネームを表示している
上記の流れを言語化すると
まず、コメントを全件取得している(DBに入っているデータを2件とする。)→1回
そして、それに紐ずくuserを1人取得する→2回
最後に、紐づいているuserを1人取得する。→3回
commentsテーブルに対して1回、userの人数分取得(今回は2回)なので計3回アクセスしていることになる。
これがN+1問題。もしこれが1000件になったら、その分DBにアクセスしなければならなくなる。
##③解決方法
結論としては、icludesメソッドを使う。
icludesメソッドにより、commentsに紐づいているuserを一気に取得できる。
仮にcommentが3つ取得できて、user_idがid=1,id=4,id=8とわかっている場合、usersテーブルから一気に持ってくることでこの問題は解決する。
class CommentsController < ApplicationController
def index
@comments = Comment.includes(:user)
end
#コメントを全件取得し,それに紐づくuserをDBから一気に取得している