Rails5.2とbelongs_toとN+1問題の話
結果
レコードに登録するときに
外部キーをidとして入れると
N+1になる
環境はこちら
rails 5.2.1 activerecord-import 0.27.0 ruby 2.5.3
なにいってんだこいつ的な感じだと思うので説明
class User < ApplicationRecord has_many :items end class Item < ApplicationRecord belongs_to :user validates :name, presence: true end
そしてItemを複数取り込みする処理があるとする
class ItemImport def execute items = User.all.limit(100).each_with_object([]) do |user, items| %w(item_a item_b item_c).each do |name| item = Item.new(user_id: user.id, name: name) next unless item.valid? items << item end end Items.import items end end
ここでN+1発生
>> ItemImport.new.execute (前略) User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 User Load (1.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 (後略)
Rails5からbelongs_toで指定した値は
入力必須のため外部IDだけ入れておくと
ちゃんと有効な値か存在チェックをしてくれるという
仕様からうまれた問題だった
item = Item.new(user: user, name: name)
とすることで
チェック不要の有効な値が入っていると認識してくれて
無駄なクエリを発行せず
Insertしてくれるのでした
おしまい!
Railsって結構オンラインプログラミングスクールの
教材として使われるけど
完全にオーバースペックだよね
っていう小話