はじめに

Rails開発で「不要なDBのクエリー処理」があります。それらを改善するためのEagerLoadingについて対応策についてメモしておきます。

N+1問題について

「N+1」問題は2つのテーブルで関連(association)している場合にありえます。
SQL文が「N+1」回分実行されてしまいパフォーマンスを低下させてしまいます。データ件数が増えれば増えるほど、この問題でパフォーマンスが落ちます。そのためこの問題が起きないように対応する必要があります。

N+1問題の実例

ユーザ情報を保持するusersテーブルと、掲示板投稿データを保持するpostsテーブルで1対Nの関係を持っている場合の例を出します。

usersモデル:

class User < ActiveRecord::Base
 has_many :posts
end

postsモデル:

class Post < ActiveRecord::Base
 belongs_to :user
end

postsコントローラ:

def index
 @posts = Post.all
end

postsビュー(postsの全データを表示):

<% @posts.each do |post| %>
 〜 なんらかの処理 〜
<% end %>

※posts.eachでSQL文「select * from posts」が実行されます

postsビュー(postsからusersのデータを取得):

<% @posts.each do |post| %>
 <%= post.user.name %>
<% end %>

※post.user.name(nameはDBカラム)でSQL文「select users.* from users where users.id = ? limit 1 ["id", 1]」がpostsの件数分実行されます

件数分実行することがN+1問題となりパフォーマンスに影響を与えてしまっています。

N+1問題をEager Loadingで改善

Eager Loadingとはあらかじめ読み込むデータを取得(1件毎ではなく)しておくことです。

postsコントローラ:

def index
 @posts = Post.all.includs(:user)
end

includsメソッドを使い、事前にusersのデータを全て取得しておきます。これによりビューで読み込む時に1件毎に読み込まなくなります。
実際は「SELECT users.* FROM users WHERE users.”id” IN (1, 2, 3, 4, 5)」のように1つのSQLが発行されるのみになります。

includesメソッドやその他EagerLoadingメソッドの参考:
http://qiita.com/k0kubun/items/80c5a5494f53bb88dc58

その他おすすめの備忘録

Tagged with:
 

コメントを残す