僕 「N+1ってデータを何回もやりとりしてしまうことのことですよね?(ぼんやり)」
先輩 「そうそう!具体的にいうとね。この例を見て欲しい」
ProductモデルとPatronモデルはアソシエーションしている前提
products = Product.all #全体の数をN件とする
#先輩「ここでN件分の一回呼び出されるよね?正確にはeachしたときなんだけど」
products.each do |product| #先輩「ここではさっきN件分呼び出されたものを、一個一個取り出す。つまりN回分呼ぶよね」
product.patrons.each do |patron|
patron.title
end
end
先輩「そうすると結局N+1回分データを取り出す作業していることはわかった?」
僕「なるほど!わかりました!」
先輩「データが少ないときには特に問題にならないかもしれないのだけど、データが数万とかたくさんのデータを扱うときにN+1問題はパフォーマンスを低下させてしまう原因になってしまうんだ。」
僕 「確かにそうですよね!解消する手段はあるんですか?」
先輩「ある!結論から言うとincludesメソッドを使うんだ。このメソッドを使うと下記の例のように2回のやりとりで済ませることができる」
products = Product.includes(:patrons).all #先輩「includedsメソッドはSQLでin句を発行してくれるin句に関しては下に解説を載せておいたから見ていみるといい。」
products.each do |product| #先輩「viewの内容は変わらないんだ。ただincludesメソッドがついているものだとここでのデータのやりとりを1回で済ませることができる。」
product.patrons.each do |patron|
patron.title
end
end