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"

これは冗長性を減らすという点ではうまく機能すると思いますが、データを効率的に取り出すにはいくつか問題があります。たとえば、userの「指定されたアイテム」 (つまり、入札の 1 つでトランザクションが存在するユーザーのアイテム) を取得するには、次のようにします。

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 を持つ User テーブルに列を作成することを考えていましたが、これは信頼できないようです。

私の質問は、正規化を維持しながら、ユーザーのトランザクションなどの情報をより簡単に取得できるように、データを構造化するより良い方法はありますか?

ありがとう!

4

2 に答える 2

2

多くの場合、正規化とパフォーマンスはトレードオフです。あなたの場合、ユーザー テーブルに追加の列を追加して、結果を効果的にキャッシュすることは理にかなっていると思います。アイテムに追加の列を追加して、トランザクションで入札したかどうかを表示することもできます.

正規化は実際には基本原則であり、正確さのために固執する必要があると感じるべきものではありません。冗長性が生じる場合でも、一般的に使用される結果をキャッシュすることも非常に優れたアプローチです。

他の唯一のオプションは、実際にキャッシュを使用することです (例: memcached)。これにより、カウントを実際のキャッシュに保存し、そのユーザーに対して新しいトランザクションが発生したときにカウントを「破棄」することができます。

于 2012-08-12T06:38:11.860 に答える
1

厳密な正規化を削除します。このようなアーカイブモデルのTransaction場合、少なくとも2つの^ user_id(sender_id、receiver_id)とitem_idを保存する必要があります。入札によってアイテムやユーザーが変更されることはないため、ここでかなり節約できます。ユーザーの名前を頻繁に表示する場合は、ユーザーの名前を保存することもできます。

非正規化されたデータベースは悪くありません。mongodbやcouchdbのようなデータベースを使用するようになると、それをより頻繁に使用するようになります。

于 2012-08-12T06:44:36.607 に答える