簡體   English   中英

如何避免N + 1查詢

[英]How to avoid N+1 query

我有以下型號:

  • 用戶
  • 能力
  • PricingRule

使用以下關系定義:

  • 用戶有很多定價規則
  • 能力有一個定價規則

在此輸入圖像描述

我們的想法是獲取符合某些條件的所有能力,並為每個能力獲取其定價規則。 但是,可以基於每個用戶定義特定能力的自定義定價規則。

目前我獲取所有匹配的能力並迭代它們:

  • 嘗試找到符合用戶定價規則的當前能力
  • 或默認為該能力的定價規則

我正在使用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_rulesabilities ,並且將使用他們的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM