2012-08-12 82 views
1

我的Rails應用程序是用戶在彼此之間交易項目的系統。用戶對物品進行出價,然後所有者批准創建交易的出價。然後,用戶可以在交易中撰寫評論(消息),以便在應用程序之外組織內容。我有它迄今結構的方法是像這樣:Rails數據庫結構和優化建議

User 
    has_many :items 
    has_many :bids 

Item 
    belongs_to :user 
    has_many :bids 

Bid 
    belongs_to :item 
    belongs_to :user 
    has_one :transaction 

Transaction 
    belongs_to :bid 
    has_many :messages 

Message 
    belongs_to :transaction 
    belongs_to :from, :class_name => "User" 
    belongs_to :to, :class_name => "User" 

我覺得這非常適用於減少冗餘方面,但我在這裏有出有效地獲取數據的幾個問題。例如,檢索user的‘給定項目’(即用戶「我做了這對投標中的一個存在交易項目):

user.items.joins(:bids).where("bids.id" => Transaction.select("bid_id")) 

或接收物品:

Item.joins(:bids).where("bids.user_id" => user.id).where("bids.id" => Transaction.select("bid_id")) 

這似乎是相當昂貴的我想要的信息。

更重要的是,我想彙總用戶的交易並顯示給定與收到的項目的比率,這些項目可能顯示在任何給定頁面上的用戶名旁邊。目前我正在做的是提取和計算所有用戶的給定和收到的項目,然後進行分割(這是非常昂貴的...)。我在考慮在用戶表上使用received_count和given_count列,每次創建或銷燬事務時都會更新,但這似乎不可靠。

我的問題是,有沒有更好的方式來構建我的數據,以便像用戶交易一樣獲取信息要簡單得多,同時保持它的規範化?

謝謝!

回答

2

正常化和性能往往是權衡。在你的情況下,我認爲向Users表中添加額外的列以有效地緩存結果是有意義的。您還可以向項目添加額外的欄目以顯示他們是否對交易進行了出價。

規範化是一個真正的基本原則,而不是你應該覺得你需要堅持正確性,即使它創造冗餘也緩存常用結果也是一個非常好的方法。

唯一的其他選擇是實際使用緩存(例如memcached)。這可讓您將計數存儲在實際的緩存中,並在該用戶發生新事務時將其「破滅」。

+0

感謝您的建議 - 這使我更加有信心爲現在添加額外的緩存列。也許我會仔細研究memcached(我正在Heroku上部署,所以直接添加額外的過程有點多..) – tom 2012-08-12 06:48:29

+0

當時機到來時,heroku使得使用memcached變得非常簡單(當然,它的成本多一點錢)。 – 2012-08-12 07:04:59

1

降低嚴格的標準化。對於像Transaction這樣的檔案模型,您至少應該存儲兩個^ user_id(sender_id,receiver_id)和item_id。出價不會更改其項目或用戶,因此您可以在此保存。如果您經常顯示這些名稱,您甚至可能希望在其上存儲用戶名稱。

非規範化的數據庫並不壞,一旦你使用像MongoDB或couchdb這樣的數據庫,你會更頻繁地使用它。

+1

謝謝,我想我也會採用這種方法。可能我對終極正常化的渴望仍然來自大學教授。 – tom 2012-08-12 07:15:00