[英]How to avoid N+1 query
我有以下型號:
使用以下關系定義:
我們的想法是獲取符合某些條件的所有能力,並為每個能力獲取其定價規則。 但是,可以基於每個用戶定義特定能力的自定義定價規則。
目前我獲取所有匹配的能力並迭代它們:
我正在使用Rails和ActiveRecord,這里到目前為止我所擁有的:
user = User.first
Ability.all.map do |a|
user.pricing_rules.matching_ability(a).first || a.pricing_rule
end
每個用戶定價規則定制應該由業務按需完成。 常見的工作流程是從能力中獲取定價規則。
任何想法或幫助讓我走上正確的道路將非常感激。
編輯:
matching_ability
實現如下:
def self.matching_ability(ability)
where(name: ability.name)
end
您可以“急切加載”以避免N + 1查詢,如下所示:
user = User.includes(pricing_rules: :abilities).first
Ability.includes(:pricing_rule).map do |a|
user.pricing_rules.matching_ability(a).first || a.pricing_rule
end
您應該在生成的SQL中看到這會LEFT OUTER JOIN
您的查詢添加LEFT OUTER JOIN
,因此ActiveRecord僅在兩個查詢中加載關聯的記錄。 特別是,用戶將在每個pricing_rule
上加載其pricing_rules
和abilities
,並且將使用他們的pricing_rules
加載這些pricing_rules
。
但是,使用where
實現matching_ability
可能會生成其他查詢,從而使您返回N + 1問題。 要利用第一個查詢中的“預先加載”,您可能需要重構為:
self.matching_ability(ability)
select{|a| a.name == ability.name}
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.