railsのn+1問題をincludesで対策
はじめに
railsアプリケーションで起こる、n+1問題
をincludes
を使って対策する方法について
n+1問題とは
n+1問題とは、1回のアクセスでいいのに何回もデータベースにアクセスしてしまい、
それによってページの読み込み速度の低下などにつながってしまうことです。
例えば、userとpostが1対多数の関係にあるとき、
@users = User.all @users.each do |user| puts user.post.content
上記のコードが実行されると、
1:まずuserの一覧を取得するためデーターベース(user)へアクセスします。
2:ローカル変数userのidに対応するpostを取得するためにデータベース(post)にアクセスします。
3:2の処理をuserの数だけ繰り返してしまう。
→つまり、ユーザーの数だけn回データベース(post)にアクセスしてしまうわけです。
どちらかというと、1+n問題です。
n+1問題の解決法
解決法はいくつかあるのですが、ここでは「includes」を使う方法をご紹介します。
仮にAモデルとBモデルがある場合、
A.includes(:B).all
こうすることで、Aに関連するBも取得できるようになります。
@users = User.includes(:post).all # ユーザーが3人の場合、ここでユーザー3人に関連するpostのデータもまとめて取得してきてくれる。 @users.each do |user| puts user.post.content
each
の前にpost
の情報も取得してきてくれるため、n+1問題が起こらなくなります。
includes
なしの場合だと、データベースに4回アクセスする(ユーザーテーブルx1回とポストテーブルx3回)のに対し、
includes
ありの場合だと2回で取得できるようになります。
なので取得するデータが多いほど、includes
の効果は顕著になります。