2012-08-12 102 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