Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

RailsのN+1問題の解決方法 初心者→中級者へのSTEP9/25

RailsのN+1問題の解決方法

はじめに
RDM楽しかったです。後々、記事にしてみせます。二日酔いです。頑張って書きます。
今回はパフォーマンスを悪くするN+1問題の解決方法についてです。

N+1問題とは

コードをみた方が早いかもしれません。下記コードをみてください。

user.rb
class User < ApplicationRecord
  has_one :blog
end
blog.rb
class Blog < ApplicationRecord
  belongs_to :user, foreign_key: "user_id"
end

わかりすいようにユーザーがブログを一つ持つようなリレーションモデルを考えます。
user#indesにて各ユーザーの名前とそのユーザーのブログ名を表示するようにします。

view/user/index.html.haml
- @users.each do |user|
  = user.name
  = user.blog.name

このコードによるクエリは以下のようになります。
スクリーンショット 2018-12-09 23.33.59.png

各ユーザーごとにBlogテーブルにアクセスしています。これがもしユーザー数が千、万、10万...となってくると非常にパファーマンスが悪いです。これがN+1問題です。(user一覧表示の為のデータ取得のSELECTが1、各ユーザのブログを取得する為のSELECTがNとなります)

パフォーマンス向上の為、ブログテーブルへのSELECTを一回にしたいです。

解決方法のincludes

解決策は簡単で、includesを使うだけです、includesメソッドは関連するテーブルをまとめて取得してくれます。

view/user/index.html.haml
- @user_index.includes(:blog).each do |user|
  = user.blog.name

スクリーンショット 2018-12-09 23.42.01.png

これでブログテーブルへのSELECTが1つになりました!!N+1問題は解決です。
※今回は1対1の関連モデルを例に説明しましたが、N対1対Nの場合、など状況によってincludesの使い方を少し考える必要があります。とりあえすincludes入れればいいや、ではなくログをみてしっかりパファーマンスが改善されているか判断してコーディングしましょう

まとめ

N+1問題を作るようなコード書くとブヒブヒ言われそうなので、意識して書かないようにしましょう。
RDMについてはこのカレンダー中に記事にできそうかわからないけど絶対記事にする。
参考先にbulletとかいう便利なgemのこと書いてあったからそれもいつか書かなきゃですな。

参考にしたの

【Rails入門】パフォーマンスが悪いならincludes/orderを検討しよう
https://www.sejuku.net/blog/26168

Railsライブラリ紹介: N+1問題を検出する「bullet」
http://www.techscore.com/blog/2012/12/25/rails%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E7%B4%B9%E4%BB%8B-n1%E5%95%8F%E9%A1%8C%E3%82%92%E6%A4%9C%E5%87%BA%E3%81%99%E3%82%8B%E3%80%8Cbullet%E3%80%8D/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What are the problem?