在檢索資料時,我在使用 Postgresql 和 Rails 計數相關模型時遇到查詢性能問題。
class MasterModel
# few fields, like name, description and such
has_and_belongs_to_many :business_models, class: 'BusinessModel'
end
class BusinessModel
# Lots of important information, many fields
has_and_belongs_to_many :master_models, class: 'MasterModel'
end
有問題的用例business_model可以與任何數量相關,master_model因此通常您應該擁有少量master_model、大量business_model甚至更多的多對多關系。
顯示master_model索引頁面時,您可以將其資訊可視化,并且delete僅在沒有關系時才啟用按鈕,因此在其表示中計算關系很重要。
所以我嘗試了一些方法來實作這一點:
- 包含關系在 ActiveRecord 中非常慢,但在查詢時卻沒有。至少它沒有N 1。
MasterModel.includes(:business_models).limit(50).offset(0).each do |master|
master.business_models.size
end
- 不包括。我們有 N 1,但只要模型分頁合理,速度就會非常快。
MasterModel.limit(50).offset(0).each do |master|
master.business_models.size
end
- 鑒于我只需要知道關系是否存在,我嘗試了一個存在的選擇。單一查詢和快速。
MasterModel.select(
:id,
:name,
:description.
'NOT EXISTS (
SELECT many.master_id
FROM many
WHERE many.master_id = master.id
) AS removable'
).limit(50).offset(0).each do |master|
master.business_models.removable
end
最后,我選擇了第三個選擇,但我并不完全相信。Rails 的方式是什么?在其他情況下我做錯了嗎?
uj5u.com熱心網友回復:
如果您使用has_many through關聯,您將能夠使用counter_cache但 HABTM 不支持counter_cache,因此您可以實作自己的counter_cache
首先,您需要將新的整數列添加到master_models名為的表中business_models_count
add_column :master_models, :business_models_count, :integer, default: 0
并將下一個代碼添加到您的模型中MasterModel
class MasterModel
has_and_belongs_to_many :business_models, class: 'BusinessModel', before_add: :inc_business_models_count, before_remove: :dec_business_models_count
private
def inc_business_models_count(*)
self.increment!(:business_models_count)
end
def dec_business_models_count(*)
self.decrement!(:business_models_count)
end
end
并撰寫一些 rake 任務,通過MasterModel記錄和更新現有記錄的計數器。
可以這樣做:
MasterModel.find_each do |master|
master.increment!(:business_models_count, master.business_models.size)
end
之后,您將能夠在沒有 N 1的情況下獲取business_models_count每個實體MasterModel
MasterModel.limit(50).offset(0).each do |master|
master.business_models_count
end
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/489078.html
標籤:轨道上的红宝石 红宝石 PostgreSQL
