5

我正在使用Rails和MySQL,並且有一個基於行計數的效率問題。我有一個Project型號has_many :donations正在存儲數據庫記錄的冗餘?

我想統計一個項目的唯一捐助者數量。

projects表中有一個名爲num_donors的字段,並且在創建新捐助者時遞增該字段是一個好主意?

或者像@num_donors = Donor.count(:select => 'DISTINCT user_id')這樣的東西在效率方面會因爲數據庫優化而變得相似或相同?這是否需要我爲user_id和我想要計數的其他字段創建索引?

相同的答案持有總和捐贈總額?

回答

10

要回答標題問題。是的,這是多餘的,但你是否應該這樣做取決於你的情況。

除非您知道性能問題,否則請在您的應用程序中即時計算計數和總計,並且不要存儲它們。也就是說,除非沒有其他選擇,否則不要存儲計算的值。

在大多數情況下,你不必訴諸於此,不應該。

如果您必須存儲計算值,請執行下列操作:

  • 不要通過遞增它跟上最新的。每次更新時重新計算所有數據的計數/總數。
  • 如果您沒有太多更新, 會將代碼更新觸發器更新爲 ,使計數/總數保持最新。
  • 數據庫的冗餘問題在於當數字 不同意時,您不確定哪個是權威性的 。添加到 文檔的注意事項來源 數據是權威的來源,如果 他們不同意並且可以被覆蓋。
7

雖然這取決於數據庫的大小,但這些是數據庫專用的操作類型,所以它們應該很快。這可能是過早優化的情況 - 您應該首先不存儲總計,從而使其更簡單 - 如果需要,可以稍後進行優化。

4

彼得和JohnFx的答案是健全的,你要建議的是你的數據庫架構的denormalization,它可以提高讀取性能,但在寫,而另外把責任推給開發商​​(或其他DBMS clevers的損害)以防止數據集內的不一致。

ActiveRecord具有一些內置的功能,可以自動管理has_many關係的計數。看看這個Railscast on counter caches

5

記住格言「有一隻手錶的男人總是知道時間,一個有兩隻手表的男人永遠不會確定。「我只會在以下情況下存儲派生的數字:

性能問題會阻止您在需要時獲取派生數字(在這種情況下這應該不是問題,因爲答案很可能來自索引)

你有理由相信,你是從通過編程錯誤或有意或無意的用戶操作主表中丟失的紀錄。在這種情況下,您可以使用您的派生號審計當前計算的數。

+0

愛的格言 - 以前沒聽過。請記住:) – nfm 2009-10-03 03:13:37

3

你知道嗎一個簡單的國旗做ActiveRecord魔術?

class ThingOwner 

# it has a column like 
# t.integer things_count, :default => 0 

has_many :things, :counter_cache => true 

end 

至於這個問題 - 是的,當然它是多餘的,我想補充這樣一個計數器,當且僅如果時間things.count的份額過大。

否則,它是過早的優化。