N+1問題を回避するrenderの書き方【Day 6/30 2nd】
【注意】本記事でN+1問題は解決しません。ただのrenderの書き方でした。自戒のために残しておきます。ただしくはこちらへ。
こんにちは、たわらです。
本記事はN+1問題と、問題を回避するrenderの書き方を整理した記事です。
N+1問題は、必要以上にSQLを発行しまうこと
SQLを発行する、ということは、データベースからデータを抽出する操作のことです。この作業が増えると、ウェブアプリケーションのパフォーマンスが落ちてしまい、ユーザーの満足度の低下につながってしまいます。
なので、SQLを発行する回数を減らしたほうがよいのですね。
具体的には、例えば次のようなコードがあります。
app/controllers/user_controller.rb
def
@user = User.all
end
app/views/index.html.erb
<ul class="users">
<% @users.each do |user| %>
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
</li>
<% end %>
</ul>
上記の書き方だと、、、
Userデータベースからユーザー一覧情報を取得して@userに格納し、さらに、eachメソッドのブロックの中で、Userの数だけ、userの情報を取得して表示しています。
ここでは、「Userデータベースからユーザー一覧情報」を1回情報を取得し、「eachメソッドのブロックの中で、Userの数だけ」(n回)情報を取得していることになります。
これがN+1問題です。
なので、SQLを発行する回数を減らす方針を取ります。
まずブロックのなかの二行を、「_user.html.rb」という部分パーシャルを作成します。
そして、こんなふうに書き換えます。
app/views/index.html.erb
<ul class="users">
<%= render @users %>
</ul>
Railsは、@usersという変数から自動的に「_user.html.rb」を探してくれます。
@usersに直接renderメソッドを使用することで、「_user.html.rb」をuserの数だけ繰り返し表示してくれます。
この場合のSQLの発行は、コントローラーで@usersを取得するときの一回だけ(のはず)です。
他に対策として、preloadメソッドやeager_loadメソッドなのだがあるみたいですが、ここでは紹介しません。
読んでくださったくださった、ありがとうございます。
この記事が気に入ったらサポートをしてみませんか?