はじめに
先日、初めてN + 1クエリ問題に遭遇したため、その対処方法を記録します。
そもそも、N + 1クエリ問題とは?
...モデル同士が関連づけられているときに、レコードを全件取得しようとすると、SQLの発行回数が増えてしまい、動作が重くなる問題。
と認識している。間違っていたらごめんなさい。
N + 1クエリ問題が発生する実際の例
例えば、以下のような3つのモデルがあるとする。
product.rb
has_many :product_properties
has_many :properties, through: :product_properties
property.rb
has_many :product_properties
has_many :products, through: :product_properties
product_property.rb
belongs_to :product
belongs_to :property
コントローラー側では、親であるProductをidから検索し、取得する。
product_controller.rb
def show
@product = Product.find(params[:id])
end
viewでは、関連先のデータを表示する。
show.html.erb
<% @product.product_properties.each do |property| %>
<%= #{property.value} %>
<% end %>
このとき、N+1クエリ問題が発生している。
対処方法
コントローラを次のように変更する。
product_controller.rb
def show
@product = Spree::Product.includes(product_properties: :property).find(params[:id])
end
こうすると、テーブルが結合されてSQLの発行回数が減る。