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の値を直書きしているからよいのかな...