• WebCamp_インタビュー
    【卒業生インタビュー】台湾で月間100万UUの訪日旅行メディアを手掛けるCEOが、プログラミングを学んで得たものとは?
    2018.01.15
  • WebCamp_インタビュー
    「自信の持てるスキルを得たい!」内定辞退した女子大生がプログラミングを学習したワケ。
    2018.04.28
  • WebCamp_インタビュー
    【WebCamp受講生インタビュー】起業準備中にCEOが気がついたプログラミングスキルの重要性とは?
    2017.12.25
  • WebCampPro_インタビュー
    未経験でも寿司職人からWebデザイナーになった!ホスピタリティでスクールを支える宮脇トレーナー
    2017.05.26
  • WebCampPro_インタビュー
    未経験31歳からエンジニア転職を実現【実際に聞いてみた】
    2017.04.01
  • WebCampPro_インタビュー
    自分で稼ぐ力をつけるため、新卒5年目の営業マンがエンジニアに転職!【WebCampPro転職者インタビュー】
    2018.02.02
  • WebCampPro_インタビュー
    未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
    2018.03.10
  • WebCamp_インタビュー
    時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】
    2018.01.26
  • WebCamp_インタビュー
    “未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
    2017.10.04
  • WebCamp_インタビュー
    【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
    2018.01.15
  • WebCamp_インタビュー
    「1カ月頑張ればこの先が見えてくる」地元メディアを立ち上げたママさん
    2017.07.20

◆当サイトで人気のプログラミング教室のおすすめランキングはこちら!
プログラミングは独学では非効率で、時間を無駄にするリスクがあります。効率的なカリキュラムで学べるスクールを受講しましょう。

WEBCAMP【マンツーマンサポート】1ヶ月短期集中でプログラミングを学ぶスクール
1ヶ月通い放題・メンター常駐の教室環境でプログラミングを学びたい方!
TechAcademyオンラインで開講しているプログラミングスクール
オンラインでどこでも学べる!/教室に行くのが忙しい人でも安心!
Tech Camp教養としてのITスキルを学べるスクール
Webデザイン/AI(人工知能)/IOS/Androidアプリ制作/VRを学びたい方!
WEBCAMP PRO転職保証付き!エンジニアとして転職したい人におすすめ!
未経験からプロのエンジニアへ3ヶ月で転職する為のスクールです!
12月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
11月生は満員となっております。12月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

はじめに

Railsアプリケーションは、データベースとブラウザの間を取り持つのが、主な役割です。

つまり、Railsアプリケーションの主な働きは、2つにまとめられます。

・データベースからデータを取得して、そのデータに適した表示画面を作る
・入力された値を適切に処理して、データベースへ記録する

そのため、通信速度とデータベースへのアクセス速度が、アプリケーションのパフォーマンスに大きな影響を与えます。

特に、データベースへのアクセス速度は、安易に作ってしまうと、データ量に応じて急激に応答が遅くなることがあります。つまり、アプリケーションの「つくり」によって大きな差が出てくるわけです。

そんなパフォーマンスを考慮したプログラムを考えるなら、ぜひincludesを利用しましょう。

includesを使うことで、データベースへのアクセス回数を減らし、アプリケーションの応答速度を上げることができるのです。

今回は、そんなincludesについて、詳しく解説していきます。

また、同様に複数のテーブルからデータを取得する以下のメソッドも、あわせて紹介します。

・joins
・preload
・eager_load

Railsのincludesとは

Railsのincludesは、関連している複数のテーブルからデータを取得してくるときのアクセス回数を大きく減らすことができるメソッドです。

また、事前に検索やフィルタリング、ソートなどをしたデータを取得することもできるため、アプリケーション側でそれらの処理を行う必要がなくなります。そのため、シンプルで効率的なプログラムになるのです。

どの程度改善できるのか、具体的な環境を作って、確認していきます。

テスト環境の作成

ここでは、関連した2つのテーブルを持つRailsアプリケーションの雛形を、scaffoldを使って作成します。

コマンドプロンプトにて、以下のコマンドを実行してください。(scaffoldの詳細は「【Rails入門説明書】scaffoldについて解説」を参照してください)

> rails new inc_test

> cd inc_test

> rails generate scaffold Saler name:string

> rails generate scaffold Item saler:references title:string price:integer

> rake db:migrate

以上の操作で、販売者のテーブルと、商品のテーブルが生成されました。次に、テーブル間の関連付けを行うため、モデルクラスにhas_many(参照される側)とbelongs_to(参照する側)の追加を行います。
(has_manyについては、「【Rails入門説明書】has_manyについて解説」を参照してください)

(app/models/saler.rb)

class Saler < ApplicationRecord
  has_many :items
end

※referencesを使用したため、参照するテーブルには、belongs_toが自動で追加されています。

テスト用に以下のデータを登録しておきましょう。(Webアプリケーションを実行してブラウザから登録する、rails consoleで登録するなどの方法がありますが、登録方法は問いません)

テーブル データ
Saler name: "Tanaka"
name: "Ohashi"
name: "Kimura"
name: "Takahashi"
name: "Ogawa"
name: "Kobayashi"
Item saler_id: 3,title: "book", price:400
saler_id: 2,title: "cap", price:8000
saler_id: 4,title: "shoes", price:1500
saler_id: 2,title: "ring", price:12000
saler_id: 1,title: "ring", price:50000
saler_id: 5,title: "computer", price:150000
saler_id: 2,title: "shirts", price:1000
saler_id: 5,title: "mouse", price:100

もし、rails consoleで登録する場合は、以下のコマンドを順に実行していくことになります。

Saler.create(name:"Tanaka")
Saler.create(name:"Ohashi")
Saler.create(name:"Kimura")
Saler.create(name:"Takahashi")
Saler.create(name:"Ogawa")
Saler.create(name:"Kobayashi")
Item.create(saler_id:3,title:"book", price:400)
Item.create(saler_id:2,title:"cap", price:8000)
Item.create(saler_id:4,title:"shoes", price:1500)
Item.create(saler_id:2,title:"ring", price:12000)
Item.create(saler_id:1,title:"ring", price:50000)
Item.create(saler_id:5,title:"computer", price:150000)
Item.create(saler_id:2,title:"shirts", price:1000)
Item.create(saler_id:5,title:"mouse", price:100)

念のため、正しく登録されていることを確認しておきましょう。

サーバーを起動して、ブラウザから「localhost:3000/salers」と「localhost:3000/items」にアクセスします。

> rails s

itemsのリストのSalerが値になっていないのは、referencesで関連付けを行ったためです。このままでは、この後の処理が確認しづらくなりますので、itemsのリストに、IDとSalerテーブルに登録されている名前が表示されるようにします。

変更するのはビューファイルです。
(app/views/items/index.html.erb)

<p id="notice"><%= notice %></p>

<h1>Items</h1>

<table>
  <thead>
    <tr>
      <th>ID</th>                        <!-- (1) -->
      <th>Saler</th>
      <th>Title</th>
      <th>Price</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @items.each do |item| %>
      <tr>
        <td><%= item.id %></td>          <!-- (2) -->
        <td><%= item.saler.name %></td>  <!-- (3) -->
        <td><%= item.title %></td>
        <td><%= item.price %></td>
        <td><%= link_to 'Show', item %></td>
        <td><%= link_to 'Edit', edit_item_path(item) %></td>
        <td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Item', new_item_path %>

コメントを追加している3行が追加、修正する部分です。

(1)と(2)はItemのIDを表示するための追加行、(3)は、salerテーブルから名前を取得するために、「item.saler」を「item.saler.name」へ変更しています。

保存後、ブラウザに戻って「localhost:3000/items」を読み込み直して、IDとSalerの名前が表示されていれば、準備完了です。

N+1問題とincludes

前述の環境構築で、ItemsのリストにSalerテーブルに登録してある名前が出力されていますので、基本的にはこれで完了だと考えがちです。

しかし、それがパフォーマンスの問題を起こしてしまう元凶なのです。

ブラウザにリストを表示した状態で、コマンドプロンプトへ戻ってみましょう。

そこには、次のようなログが出力されています。

Processing by ItemsController#index as HTML
  Rendering items/index.html.erb within layouts/application
  Item Load (1.0ms)  SELECT "items".* FROM "items"
  └app/views/items/index.html.erb:17
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (1.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (1.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Rendered items/index.html.erb within layouts/application (62.8ms)
Completed 200 OK in 326ms (Views: 301.6ms | ActiveRecord: 6.0ms)

これは、リストを表示するためにデータベースへアクセスした内容(SQL)が出力されているものです。

今回のリスト表示では、合計で9回データベースへアクセスしているということを表しています。この9回というのは、リストに出力された行数+1回です。

つまり、今のままでは、データベースに登録されたデータの数+1回アクセスしなければ、リストの表示ができません。それは、このままでは、もしデータの数が100件、10,00件と増えたら、リストの表示に10倍、100倍の時間が必要になるということです。

これは「N+1問題」として知られているもので、Webアプリケーションのパフォーマンスを考慮する上で重要な改善ポイントなのです。

データベースへのアクセスは、ログに出力されるように、実際はSQLコマンドによって行われます。そのため、この改善は「最適なSQL文を作成する」ことで行われるのが一般的です。

しかし、Railsには、そのSQL文を自動で作ってくれるメソッドが、すでに準備されています。それが、「includes」をはじめとしたメソッドなのです。

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
2017-10-04 10:26
今回の記事では、未経験からWebCampを1ヶ月受講し、その後エンジニアとして転職をした喜田さんにお話を伺いました。 <プロフィール> 喜田 大介 さん (28歳) 大学時代はプ...

includesで効率の良い処理を

では、実際にincludesを使って改善していきましょう。

今回の環境で修正するのは、scaffoldが自動生成した、Itemコントロールのindexメソッドの処理です。

(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.all
  end
  :

この、「Item.all」の部分がN+1問題の元凶です。

allメソッドは、ただ指定のテーブルのデータを取得してくるだけのメソッドです。そのため、Itemの各行を表示するときに、Salerテーブルから名前を取得するためのアクセスが発生していました。

この部分を変更することで、パフォーマンスの向上を図ります。

なお、上記のallメソッドを含めて、データベースへアクセスするためのメソッドは以下の5種類存在しています。

メソッド 説明 関連テーブルの事前読み込み
(associationのeager loading)
生成したテーブルの保持
(JOIN)
all テーブルのすべてのレコードを取得する しない 生成しない
joins テーブルの指定した条件のレコードを取得する しない 保持する
eager_load 関連テーブルの条件が一致するデータと指定テーブルのデータを取得する する 保持する
preload 関連テーブルの条件が一致するデータと指定テーブルのデータを取得する する 保持しない
includes 関連テーブルの条件が一致するデータと指定テーブルのデータを取得する する 必要に応じて保持する

N+1問題を解消するために重視するのは、関連テーブルの事前読み込み(associationのeager loading)です。この処理を行っていれば、すでにメモリ上に関連テーブルがありますので、いちいちデータベースへアクセスする必要がないわけです。

構文は、それぞれ以下のようになっています。

# all
モデル.all

# joins
モデル.joins(テーブル)  # 指定されたテーブルを結合
モデル.joins(条件)      # 条件に合致するカラムを結合

# eager_load
モデル.eager_load(テーブル)

# preload
モデル.preload(テーブル)

# includes
モデル.includes(テーブル)

実際に動かして確認してみましょう。

joins

以下のように修正して、ブラウザで「localhost:3000/items」を再読み込みしてください。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.joins(:saler)
  end
  :

コマンドプロンプトのログを確認すると、allメソッドと同じく、データベースへのアクセスが9回発生しています。

Processing by ItemsController#index as HTML
  Rendering items/index.html.erb within layouts/application
  Item Load (0.0ms)  SELECT "items".* FROM "items" INNER JOIN "salers" ON "salers"."id" = "items"."saler_id"
  └app/views/items/index.html.erb:17
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (1.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  CACHE Saler Load (0.0ms)  SELECT  "salers".* FROM "salers" WHERE "salers"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
  └app/views/items/index.html.erb:20
  Rendered items/index.html.erb within layouts/application (74.8ms)
Completed 200 OK in 318ms (Views: 296.7ms | ActiveRecord: 6.0ms)

joinsは、関連テーブルの事前読み込みを行いませんので、N+1問題が発生しています。
「【Rails入門説明書】joinについて解説」でjoinsについて詳しく解説していますので、参考にしてください)

eager_load

次に、eager_loadメソッドを試してみましょう。indexメソッドを次のように修正して、ページを再読み込みしましょう。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.eager_load(:saler)
  end
  :
Processing by ItemsController#index as HTML
  Rendering items/index.html.erb within layouts/application
  SQL (0.0ms)  SELECT "items"."id" AS t0_r0, "items"."saler_id" AS t0_r1, "items"."title" AS t0_r2, "items"."price" AS t0_r3, "items"."created_at" AS t0_r4, "items"."updated_at" AS t0_r5, "salers"."id" AS t1_r0, "salers"."name" AS t1_r1, "salers"."created_at" AS t1_r2, "salers"."updated_at" AS t1_r3 FROM "items" LEFT OUTER JOIN "salers" ON "salers"."id" = "items"."saler_id"
  └app/views/items/index.html.erb:17
  Rendered items/index.html.erb within layouts/application (33.9ms)
Completed 200 OK in 909ms (Views: 891.8ms | ActiveRecord: 1.0ms)

eager_loadメソッドの場合、データベースへのアクセスが1回だけになっています。データの数が少ないので、体感速度に大きな違いはない(むしろ遅く感じる場合もあります)かもしれませんが、この処理回数の違いは、データの数が大きくなると大きな違いになってくるのです。

また、関連テーブルも結合して生成したテーブルを保持していますので、絞り込みなども高速に行うことができます。しかし、その分メモリを多く消費しますので、データ量やアクセスするユーザーの数が増えると、システムへの負担が大きくなるでしょう。

preload

preloadメソッドも、eager_loadとほぼ同じように、データベースへのアクセス回数を減らすことができます。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.preload(:saler)
  end
  :
Processing by ItemsController#index as HTML
  Rendering items/index.html.erb within layouts/application
  Item Load (1.0ms)  SELECT "items".* FROM "items"
  └app/views/items/index.html.erb:17
  Saler Load (0.0ms)  SELECT "salers".* FROM "salers" WHERE "salers"."id" IN (?, ?, ?, ?, ?)  [["id", 3], ["id", 2], ["id", 4], ["id", 1], ["id", 5]]
  └app/views/items/index.html.erb:17
  Rendered items/index.html.erb within layouts/application (46.9ms)
Completed 200 OK in 349ms (Views: 322.6ms | ActiveRecord: 4.0ms)

preloadメソッドはSQLを分けてアクセスするため、アクセス数が2回になっています。しかし、データ量が増えても2回のままですので、allメソッドやjoinsメソッドのようにN+1問題とは無縁です。

1回のアクセスで済むeager_loadメソッドよりは速度の面で劣りますが、生成したテーブルを保持しませんので、メモリ消費は抑えられます。そのため、巨大なテーブルを扱うときに適しているでしょう。ただし、テーブルを保持していないため、絞り込みや並べ替えなどができません。

includes

今回の主役のincludesも、N+1問題には無縁のメソッドです。確認してみましょう。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler)
  end
  :
Processing by ItemsController#index as HTML
  Rendering items/index.html.erb within layouts/application
  Item Load (1.0ms)  SELECT "items".* FROM "items"
  └app/views/items/index.html.erb:17
  Saler Load (0.0ms)  SELECT "salers".* FROM "salers" WHERE "salers"."id" IN (?, ?, ?, ?, ?)  [["id", 3], ["id", 2], ["id", 4], ["id", 1], ["id", 5]]
  └app/views/items/index.html.erb:17
  Rendered items/index.html.erb within layouts/application (23.9ms)
Completed 200 OK in 236ms (Views: 218.4ms | ActiveRecord: 4.0ms)

preloadメソッドと同じく、データベースへのアクセスは2回で、高速な処理が期待できます。

また、includesメソッドの場合は、必要に応じて生成したテーブルを保持しますので、eager_loadメソッドとpreloadメソッドの良いとこどりをしたようなメソッドと言えます。

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】
2018-03-22 23:28
今回の記事では、独学でPHPを1年半学習し、その後WebCampを受講して未経験からエンジニアへと転職された佐々木さんにお話を伺いました。 <プロフィール> 佐々木 祐樹 さん(2...

絞り込みと並べ替え

ここまでの説明で、includesメソッドについての説明は終わりですが、最後に絞り込みと並べ替えについて、説明しておきます。

絞り込みは「where」

データベースからテーブルを取得するときに、whereメソッドで取得するデータの条件を設定することで、絞り込みを行うことができます。
(whereメソッドの詳細については、「【Rails入門説明書】whereについて解説」を参照してください)

whereメソッドは、ActiveRecordオブジェクトのメソッドですので、オブジェクトがあれば単体でも利用できますが、includesメソッドなどと組み合わせることで、データ取得と絞り込みを一気に行って、パフォーマンスを向上させることができるのです。

例えば、以下のようにすることで、金額(price)が5,000円未満のもののItemリストを表示できます。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).where("price <= ?", 5000)
  end
  :

また、Ohashiさんからの出品商品だけを確認したい場合は、関連付けしているSalerテーブルから名前を取得するため、以下のような記載になります。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).where(salers: {name: "Ohashi"})
  end
  :

並べ替えは「order」

includesなどで取得したテーブルを、任意のカラムで並べ替えるには、orderメソッドを利用します。

orderメソッドは、以下のような構文で利用します。

モデル.order(ソート式)

いくつか具体的な例をあげますので、プログラムコードを確認してください。

特定のカラムで昇順

金額の昇順で並べ替えてみましょう。

並べ替えのデフォルト設定は昇順になっていますので、昇順の並べ替えの場合は、キーとなるカラムを指定するだけになります。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).order("price")
  end
  :

なお、カラムの指定は、文字列だけではなく、以下のような指定の方法でも構いません。

    @items = Item.includes(:saler).order("price")          # 文字列
    @items = Item.includes(:saler).order(:price)           # シンボル
    @items = Item.includes(:saler).order("price ASC")      # 文字列
    @items = Item.includes(:saler).order(:price => :asc)   # シンボル
    @items = Item.includes(:saler).order(price: "asc")     # 昇順指定を文字列
    @items = Item.includes(:saler).order(price: :asc)      # 昇順指定をシンボル

昇順であることを表すASCを付加した方が、プログラムコードの可読性は上がるかもしれません。

特定のカラムで降順

降順にする場合は、降順指定を行います。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).order("price DESC")
  end
  :

記載方法は昇順と同じく、様々な方法が使用できます。

複数のカラムで並べ替え

複数のカラムを並べ替え条件にすることもできますが、デフォルトでは必ず降順指定が必要です。

商品名の降順、金額の昇順で並べ替えましょう。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).order("title DESC", "price ASC")
  end
  :

関連付けされたテーブルのデータで並べ替える

関連付けされたテーブルのカラムを指定することで、関連付けされたデータで並べ替えることもできます。

出品者名で並べ替える場合は、次のようになります。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.includes(:saler).order("salers.name")
  end
  :

未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
2018-03-10 14:42
今回の記事では、たまたま見たテレビ番組がきっかけでエンジニアに興味を持ち、WebCampProを受講して見事転職を決めた中村さんにインタビューしました。 <プロフィール> 中村 駿...

まとめ

Railsのデータベースアクセス用メソッド、includesの説明を行いました。

どんなに素晴らしいサービスを作っても、応答速度が遅くては使い勝手が悪く、誰も使ってくれません。そのため、パフォーマンス問題は、Railsアプリケーションを作る上では、避けては通れないところでしょう。

もちろん、RailsをはじめとしたWebアプリケーションは、ネットワークを介して動作しますので、ある程度の応答時間がかかることもあります。しかし、そのこととアプリケーションのパフォーマンスは別問題です。

includesを使ってN+1問題を避け、「アプリケーションが遅い」ということがないようにしていきましょう。


・includesメソッドは、関連している複数のテーブルからデータを取得してくるときのアクセス回数を大きく減らすことができる
・N+1問題というのは、データベースからデータ取得するときに、データの数+1回のデータベースアクセスが発生すること
・allメソッドやjoinsメソッドは、N+1問題を起こすため、データが多くなるとパフォーマンスに影響が出る
・eager_loadメソッドは、1度のアクセスで関連付けられたテーブルと生成したテーブルを取得するので、もっとも早いがメモリの消費量が多い
・preloadメソッドは、eager_loadメソッドと同じだが生成したテーブルを保持しないのでメモリにやさしい。しかし絞り込みなどが行えない
・includesメソッドは、場合によってeager_loadメソッドとpreloadメソッドのどちらかの動きをする柔軟性のあるメソッド
・whereメソッドを付記することで、絞り込みができる
・orderメソッドで並べ替えができる

WebCamp・WebCamp Proについて

WebCampは1ヶ月でプログラミング・Webデザインスキルを学ぶ通い放題のプログラミングスクールです。WebCamp Proは3ヶ月間で未経験から即戦力エンジニアを育成するプログラミングスクールです。

2つのサービスを運営するインフラトップでは、「学びと仕事を通して人生を最高の物語にする」という理念で会社を経営しています。

キャリアアップを目指す方は、この機会に私達と一緒にプログラミングを学んでみませんか?

12月枠も残りわずか当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
11月受入枠は満員となっております。12月枠に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

▼未経験から1ヶ月でWebデザイン・プログラミングを学びたい方はこちら!

▼ついに開講!オンラインでWebデザインを学びたい方はこちら!

 

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
2018-01-15 13:23
今回の記事では、WebCampで1ヶ月間Rubyを学習し、Webエンジニアとして転職した卒業生の田中さんにお話を伺いました。 <プロフィール> 田中 デニス 昭彦さん(...
関連キーワード
Ruby on Railsの関連記事
  • 【Rails入門説明書】includesについて解説
  • 【Rails入門説明書】RubyとRailsの初心者/中級以上用の厳選本8選
  • 【Rails入門説明書】joinsについて解説
  • 【Rails入門説明書】 jQueryの導入方法について解説
  • 【Rails入門説明書】scopeについて解説
  • 【Rails入門説明書】has_manyについて解説
おすすめの記事