0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

表示速度を上げるための個人的な考察 N+1問題編 

Posted at

N+1問題:データベースからデータを取り出す際に、大量にSQLが発行されて
動作が遅くなってしまう問題のことです。SQLとはデータベースとのやりとりをする際に用いるデータベース型言語(プログラミング言語ではないので注意)です。

実際にN+1問題が発生している様子を見ていきましょう。
N+1問題は1対多のアソシエーションの場合に多くみられるので、投稿一覧ページを見ていきたいと思います。

ra.jpg

投稿一覧ページを表示した際のターミナルです。
見てわかる通り、多くのSQL文が発行されています。
いろいろな機能をつけていてSQL文が複雑になっているので簡単な例を用いて説明します。

def index
    @posts = Post.all   #データベース上から投稿データを取得
end

投稿一覧ページに関するメソッド定義です。

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

投稿一覧のviewの定義です。

この場合、まず、
(1)投稿内容の全件取得を行います。 1回
(2)N個ある投稿一つ一つに紐づいているユーザーを取得してくる N回

合計でN+1回の処理を行っている。つまり、投稿データの個数Nの値が膨大になるにつれて、それに紐づいているUserテーブルへのアクセス回数も膨大となります。
このようなN+1問題の対策の一つとして

def index
    @posts = Post.all   #データベース上から投稿データを取得
end

の部分を

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

に変えると良い。
includes()メソッドを用いることで、投稿に紐づいているユーザーを一回で全て取得することが可能となり、処理速度を改善することが可能となる。

また投稿一覧の表示個数を分割することで処理速度を改善することができると考えられる。それに関してはまた次回。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?