カテゴリ: Rails 更新日: 2026/01/09

RailsモデルとActive Record基礎|N+1問題を避けるためのincludes・eager_load・preloadとBulletの使い方

N+1を避ける:includes/eager_load/preload とBulletの使い方
N+1を避ける:includes/eager_load/preload とBulletの使い方

先生と生徒の会話形式で理解しよう

生徒

「Railsで画面を表示しただけなのに、動きがすごく遅くなることがあるんですが、なぜですか?」

先生

「それはN+1問題が原因かもしれません。Rails初心者が必ず一度はつまずくポイントです。」

生徒

「N+1って数字みたいで、まったくイメージできません……」

先生

「大丈夫です。買い物や配達の例えで、ゆっくり説明していきましょう。」

1. N+1問題とは?Rails初心者が最初に知るべき落とし穴

1. N+1問題とは?Rails初心者が最初に知るべき落とし穴
1. N+1問題とは?Rails初心者が最初に知るべき落とし穴

N+1問題とは、RailsやActive Recordを使ったときに、 データベースへのアクセス回数が必要以上に増えてしまう問題です。 プログラム自体は正しく動いているのに、 画面表示が遅くなる原因になります。

例えば、10件の記事を表示し、それぞれに投稿者名を表示する場合を考えてみてください。 記事を1回取得し、そのあと投稿者を10回取得すると、 合計で11回もデータベースに問い合わせることになります。

これが「N件 + 追加で1件」のように増えていくため、 N+1問題と呼ばれています。 初心者の方は、「1つずつお店に買い物に行く」イメージを持つと分かりやすいです。

2. N+1問題が起きる基本的なコード例

2. N+1問題が起きる基本的なコード例
2. N+1問題が起きる基本的なコード例

Railsでは、モデル同士の関連(アソシエーション)を使うと、 とても自然な書き方ができます。 しかし、この便利さがN+1問題を生みやすくします。


posts = Post.all
posts.each do |post|
  puts post.user.name
end

このコードは一見シンプルですが、 記事を取得したあと、ループの中で毎回ユーザーを取得しています。 データが増えるほど、動作がどんどん遅くなります。

3. includesとは?まとめて読み込む基本テクニック

3. includesとは?まとめて読み込む基本テクニック
3. includesとは?まとめて読み込む基本テクニック

N+1問題を避けるために、Railsでは includesという便利な仕組みが用意されています。 これは「必要なデータを最初にまとめて取っておく」方法です。

例えるなら、1件ずつ配達を頼むのではなく、 まとめて段ボールで届くイメージです。


posts = Post.includes(:user)
posts.each do |post|
  puts post.user.name
end

includesを使うことで、 Railsが自動的に最適な方法でデータを取得してくれます。 初心者の方は、まず「N+1を見たらincludes」 と覚えておくと安心です。

4. preloadとeager_loadの違いをやさしく理解する

4. preloadとeager_loadの違いをやさしく理解する
4. preloadとeager_loadの違いをやさしく理解する

includesの仲間として、 preloadeager_loadがあります。 名前は難しそうですが、考え方はシンプルです。

preloadは、「別々にまとめて取る」方法です。 eager_loadは、「最初から結合して一気に取る」方法になります。


Post.preload(:user)
Post.eager_load(:user)

普段はincludesを使えば十分ですが、 条件検索や並び替えを関連先で行う場合は、 eager_loadが必要になることがあります。 最初は深く考えすぎなくても大丈夫です。

5. Bulletとは?N+1問題を教えてくれる先生役

5. Bulletとは?N+1問題を教えてくれる先生役
5. Bulletとは?N+1問題を教えてくれる先生役

N+1問題は、見た目だけでは気づきにくいのが厄介な点です。 そこで役立つのがBulletというツールです。

Bulletは、N+1問題が発生したときに、 「ここで無駄な読み込みがありますよ」と 教えてくれる見張り役のような存在です。


gem 'bullet'

開発中にBulletを使うことで、 初心者でもパフォーマンスの悪化に気づきやすくなります。 Railsで長く開発するなら、早めに慣れておくと安心です。

6. N+1を避ける意識を身につけることが大切

6. N+1を避ける意識を身につけることが大切
6. N+1を避ける意識を身につけることが大切

N+1問題は、RailsやActive Recordを使う以上、 避けて通れないテーマです。 ですが、仕組みを理解すれば怖いものではありません。

「ループの中で関連データを呼んでいないか」 「まとめて取得できないか」 こうした意識を持つだけで、 アプリの動作は大きく変わります。

初心者のうちは、includesとBulletを味方につけて、 安心してRailsのモデル設計を進めていきましょう。

関連記事:
カテゴリの一覧へ
新着記事
New1
Ruby
Rubyプログラムの実行方法まとめ:スクリプト・REPL・Shebang・実行権限の基本
New2
Rails
アセットの全体像をやさしく解説!importmap・jsbundling・cssbundlingの選び方
New3
Rails
Rails Action Cable入門|チャネル・接続・サブスクライブの基本を図解でやさしく解説
New4
Rails
RailsのScaffoldは使うべき?初心者向けにメリット・デメリット・安全な使い方と代替案を解説!
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyのreduceとinject入門!合計計算や集計を初心者向けに分かりやすく解説
No.2
Java&Spring記事人気No2
Ruby
Rubyの文字列エンコーディング完全ガイド!Encoding・force_encoding・encodeを初心者向け解説
No.3
Java&Spring記事人気No3
データベース
PostgreSQLのWHERE句を徹底解説!初心者でもわかるSQLデータ抽出の基本
No.4
Java&Spring記事人気No4
Rails
Rails認可をやさしく理解!CanCanCan入門:ability.rbの定義とload_and_authorize_resource実例
No.5
Java&Spring記事人気No5
Ruby
Rubyで比較演算子を完全解説!==・===・<=>・eql? の使い分け
No.6
Java&Spring記事人気No6
Ruby
OpenSSL関連エラーの直し方を完全解説!証明書・ビルドオプション・brew対策まとめ
No.7
Java&Spring記事人気No7
データベース
MySQLとは?初心者向けにデータベースの特徴とできることをやさしく解説
No.8
Java&Spring記事人気No8
データベース
PostgreSQLのCTE(WITH句)完全解説!複雑なSQLを整理して読みやすくする書き方