Rails数据库结构和优化建议

时间:2012-08-12 05:35:19

标签: mysql ruby-on-rails database postgresql activerecord

My 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"))

对于我想要的信息而言似乎相当昂贵。

更重要的是,我希望汇总用户的交易,并显示给定项与已接收项的比率,这些项可能显示在任何给定页面上用户名旁边。目前我正在做的是获取和计算所有用户的给定和收到的项目然后分割(这是非常昂贵的......)。我想在User表上有一个列,其中receive_count和given_count每次创建或销毁一个Transaction时都会更新,但这似乎不可靠。

我的问题是,有没有更好的方法来构建我的数据,以便获得像用户的交易这样的信息更简单,同时保持标准化?

谢谢!

2 个答案:

答案 0 :(得分:2)

通常,规范化和绩效是权衡取舍。在您的情况下,我认为将额外的列添加到Users表以有效地缓存结果是有意义的。您还可以向项目添加额外列,以显示他们是否已通过交易进行出价。

规范化实际上是一个基本原则,而不是你应该认为你需要坚持正确性,缓存常用结果,即使它创建冗余也是一种非常好的方法。

唯一的另一种选择是实际使用缓存(例如memcached)。这将允许您将计数存储在实际缓存中,并在该用户发生新事务时“破坏”它们。

答案 1 :(得分:1)

放弃严格的规范化。对于像Transaction这样的归档模型,您至少应该在其上存储两个^ user_ids(sender_id,receiver_id)和item_id。出价不会更改其项目或用户,因此您可以在此处保存。如果经常显示这些名称,您甚至可能希望在其上存储用户名。

非规范化数据库也不错,一旦你使用像mongodb或couchdb这样的数据库,你就会更频繁地使用它。