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 3 years have passed since last update.

【第1回】RailsのN+1問題と解決するためのメソッド完全版

Posted at

この記事では、N+1問題の正しい理解と、解決するためのメソッドを紹介します。
第1回では、N+1問題とはなにか、そしてどのような状態で発生するのかを具体例とともに解説します。
この記事を読むことで、N+1問題の正しい理解、ケースに応じたN+1問題を解決するメソッドの使い分けができるようになるはずです。

##本記事の内容

  • N+1問題とは
  • N+1問題が発生する状況
  • SQLが発行されるタイミング

##開発環境

  • Ruby 2.7.2
  • rails 6.1.0

##アソシエーション
スクリーンショット 2021-06-22 22.36.22.png
usersテーブルとpostsテーブルが1対多の関係でアソシエーションされています。
ユーザー1人に対して、投稿を複数持っている基本的な構成です。

それではさっそくいきましょう。

##N+1問題とは
N+1問題とは、1つのテーブルへのSQL発行と、複数回(N回)の関連テーブルへのSQL発行がおこなわれてしまうことです。
わかりやすくいうと、eachメソッドなどのループ処理のときに、大量のSQLが発行されてしまうことです。
具体例をみていきましょう。

##N+1問題が発生する状況

ruby.rb
User.limit(5).each do |user|
 p user.posts
end

SQLを確認してみましょう。

ターミナル
User Load (1.7ms)  SELECT "users".* FROM "users" LIMIT $1  [["LIMIT", 5]]
Post Load (1.2ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1 /* loading for inspect */ LIMIT $2
Post Load (1.4ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1 /* loading for inspect */ LIMIT $2
Post Load (2.8ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1 /* loading for inspect */ LIMIT $2 
Post Load (2.1ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1 /* loading for inspect */ LIMIT $2
Post Load (1.7ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1 /* loading for inspect */ LIMIT $2 

usersテーブルに対して1回SELECT句を発行し、それぞれのユーザーに紐づく投稿をpostsテーブルから5回取得しています。N+1問題とは、はじめの1回で軸となるモデル(テーブル)を取得し、そのモデルに対するデータ数分(N回)のSQLが実行されてしまう状態のことです。

今回はlimitメソッドでデータ取得数を制限しましたが、N+1問題は、そのデータ量に比例してパフォーマンスが劣化してしまいます。初学者のポートフォリオレベルでは気にならないかもしれませんが、実務では何万、何十万とデータを扱うので、決して無視できません。

現状データ量が少ないとしても、サービスの成長とともにパフォーマンスの劣化は避けられないです。
また、大量のSQLを発行することはDBに高負荷を与えることにもつながり別な問題を発生させる原因にもなります。
とくに1対多のアソシエーションで発生することが多いです。

##SQLが発行されるタイミング
RailsでSQLが発行されるタイミングは、SQLの実行結果をアプリケーションで使用するときです。

ruby.rb
User.limit(5).each do |user|
 p user.posts #=>このタイミングでSQLが発行される
end

どのタイミングでSQLが発行されるのか理解することで、パフォーマンスを意識した開発が可能になります。
ぜひ自分のポートフォリオを見直してみて、改善できそうなところを見つけてみてください。
N+1問題を解決するメソッドについては、次回まとめていきます。

##まとめ

  • N+1問題とは、1つのテーブルへのSQL発行と、複数回(N回)の関連テーブルへのSQL発行がおこなわれてしまうこと。
  • とくに1対多のループ処理で発生しやすい。
  • RailsでSQLが発行されるタイミングは、SQLの実行結果をアプリケーションで使用するとき。

##参考文献
Railsガイド
【Ruby on Rails】N+1問題ってなんだ?

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?