N+1問題とは
必要以上にSQLが発行されてしまい動作が悪くなってしまう問題の事です。
SQLとは
データベースを操作するための言語です。データを挿入したり検索したりする際に利用します。
データベースとのやり取りを必要以上にしてします状態という事ですね。
具体的にどんなときに起こるか
犬と飼い主を例にしていきます。
#owner.rb
class Owner < ActiveRecord::Base
has_many :dogs
end
#dog.rb
class Dog < ActiveRecord::Base
belongs_to :owner
end
飼い主と犬のアソシエーションを定義しました。
一人のownerは複数のdogsを持つ関係です。
N+1問題が起きてしまうコード
#controller
@owners = Owner.all
#view
@owners.each do |owner|
owner.dogs.each do |dog|
dog.name
end
end
このコードではOwners.all
でownersテーブルに一回のアクセスがSQLによって行われました。
そしてviewのコードで飼い主の数を取得した後に一人一人の飼い主に対しての犬の数だけdogsテーブルにSQLが送られます。
#N+1問題
ownersテーブルへのアクセス1回 + 関連するdogsテーブルへのアクセスがN回
これをincludesメソッド
で解決できます。
includesメソッド
引数にアソシエーションで定義した関連名を指定して定義します。
モデル名.includes(:関連名)
先程の例を当てはめると
@owners = Owner.includes(:dogs)
これだけで解決します。
最後に
読んでいただいた方、ありがとうございました。