N+1問題とは

  • 51
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

Railsを扱っていると頻繁にN+1問題というものを聞く。

N+1問題とは何か?

N+1問題とは、え!そんなにSQL発行されるんですか!?というやつである。

N+1問題が潜む可能性があるのはどこか?

SQLの発行回数を抑えたいのは、常識の範囲であるので、レビューとか自分の書いてるコードとかで、どのようなときにN+1を注意すべきなのかというのが重要なところである。

こうなってたら注意しよう

モデルで、has_manyそしてbelongs_toを持っているものがあれば、N+1問題が発生する可能性がある。そうなっているモデルのコードをレビューもしくは扱うときは注意してコードを観察しよう。

HogeモデルとFooモデルがあるとして、

class Hoge < ActiveRecord::Base
  has_many :foos
class Foo < ActiveRecord::Base
  belongs_to :hoge

このように定義されているとする。

Hoge.all.each do |hoge|
  p hoge.foos
end

Foo.all.each do |foo|
  p foo.hoge
end

としてしまうと、eachの中で紐付いたモデルを取りに行くためSQLが毎回発行されてしまう。

includesとかで解決

Hoge.all.includes(:foos).each do |hoge|
  p hoge.foos
end
Foo.all.includes(:hoge).each do |foo|
  p foo.hoge
end

と書くと、N+1問題は起きなくなる。
具体的には、IN句でいっきに読み込んでくれる。

疑問

INって遅いイメージがあるので、基本使わないようにしてたイメージがるのだが、よいのだろうか....
サブクエリーを使うわけなじゃなくて、INに欲しいIDの値を直書きしているからよいのかな...