4,000 3 C 6,000 案件ID 案件名称 A A案件 B B案件 C C案件 sales = Sales.all # SELECT * FROM sales sales.each do |s| s.business # SELECT * FROM business WHERE id = ? が sales数分発生 end —- N+1 が起きちゃうケース • 1 Request で 1クエリが発⾏され、その結果の関連情報のためN回分クエリが発⽣する • データの規模が少なければよいが、Nが多いとパフォーマンスが悪化する • ActiveRecord であれば includes などを利⽤することで対処ができる # SELECT * FROM sales # SELECT * FROM businesses WHERE id IN (“A”, “B”, “C”) sales = Sales.includes(:business).all sales.each do |s| s.business # メモリから読み込むぞ end —- N+1 を防いだケース
• 要件次第でキャッシュ期間などを考える必要がある 読み込み時Cache 販売管理 システム 取引先 マスタ Cache class SalesListDto # 省略 def customer partner_repository.load(customer.id) end end — class PartnerRepository def load(id) Rails.cache.fetch(“#{cache_key_with_version}/partner”, expires_in: 1.hour) do PartnerClient.fetch(id) end end end – 注: 参考コード, 実際にはDTOからrepositoryへの参照を行わないように実装するなどする