未経験からエンジニア 奮闘記

未経験からエンジニアに自由に生きる途中

MENU

Rails N + 1 INNERJOIN

N + 1とは?

関連するレコードを無駄に見に行ってしまう事

具体例

前提

UserとAirticleで1対多の関係

  • controller
AirticleController

def index
  @airtcles = Airticle.all
end
  • view
<% @airtcles.each do |airtcle| %>
    <%= airtcle.user.email%>
<% end %>
  • 発行されるsql

無駄にAirticleの件数分だけ、userにアクセスしてしまう 今回だとAirticleが2件なので、Userテーブルにも2回問い合わせる Airticleが100件だったら Atirtcleに1回 Userに100回問い合わせるのでDBへの問い合わせ回数が101回になる

101回の問い合わせを2回に済ませられる

SELECT 'articles'.* FROM 'articles' # Article.all の実行

SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 1 LIMIT 1 # article.user.name を実行する際に走る
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 2 LIMIT 1

解決策

AirticleController

def index
  @airtcles = Airticle.includes(:user)
end
  • sqlが2回だけ呼ばれる
SELECT 'article'.* FROM 'articles'

SELECT 'users'.* FROM 'users' WHERE 'users'.'id' IN (1, 2)

深く理解

これは、INNER JOINが行われている。テーブルの結合

テーブル結合する意味

テーブル結合をしないと、Airticleを見に行って、Userテーブルを見に行く。

テーブルを結合すると一つのテーブルを見にいく感じになる

結合方法には2つある

  • inner join

両方のテーブルで一致するモノがあるモノだけを取得

  • outer join

両方のテーブルで一致しないモノも含めて取得

参考記事

qiita.com

  • inner join

qiita.com

  • inner join outter join違い

zenn.dev

おすすめ動画

www.youtube.com