1

我的 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"

我认为这在减少冗余方面效果很好,但我在有效地获取数据方面遇到了一些问题。例如,要检索 auser的“给定项目”(即其中一个投标存在交易的用户项目),我正在做:

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 表上有一个带有 received_count 和 given_count 的列,每次创建或销毁事务时都会更新,但这似乎不可靠。

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

谢谢!

4

2 回答 2

2

正常化和性能通常是权衡取舍。在您的情况下,我认为将额外的列添加到 Users 表以有效地缓存结果是有意义的。您还可以在项目中添加一个额外的列,以显示他们是否有交易出价。

规范化确实是一个基本原则,而不是你应该觉得你需要坚持正确性的东西,缓存常用结果即使它会产生冗余也是一个非常好的方法。

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

于 2012-08-12T06:38:11.860 回答
1

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

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

于 2012-08-12T06:44:36.607 回答