りゅうじの学習blog

学習したことをアウトプットしていきます。

N+1問題

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)

これだけで解決します。

最後に

読んでいただいた方、ありがとうございました。