【发布时间】:2015-07-21 19:42:34
【问题描述】:
我正在开发一款游戏,用户可以使用虚拟货币购买虚拟物品,并将这些物品赠送给其他用户。我们需要能够跟踪物品的历史(谁购买了它,它被赠送给了谁,等等)和当前所有者。我正在为一些表格设计而苦苦挣扎。
我的想法是有这个(表格设计稍微简化,约束/键/等省略空间):
TABLE order
id INT NOT NULL AUTO_INCREMENT,
buyer_id INT NOT NULL,
paid INT UNSIGNED NOT NULL,
owned_item_id INT NOT NULL,
------------------------------------------------------
TABLE owned_item
id INT NOT NULL AUTO_INCREMENT,
store_product_id INT NOT NULL,
owner_id INT NOT NULL,
------------------------------------------------------
TABLE gift
id INT NOT NULL,
giver_id INT NOT NULL,
receiver_id INT NOT NULL,
owned_item_id INT NOT NULL,
我们的想法是,在购买商品时,会同时为该商品创建 order 和 owned_item。如果该项目是赠品,则在 gift 表中创建一个新条目并更新 owner_id 字段。
这种方法可以很容易地确定谁当前拥有给定的项目。 但是,它具有冗余数据,并为数据完整性问题留下了空间。如果“owner_id”字段设置不正确,我们最终可能会记录到一件物品由 A 购买并赠送给 B,但现在却莫名其妙地归 C 所有。
这样的结构应该如何规范化?我考虑过删除 owned_item 表:
TABLE order
id INT NOT NULL AUTO_INCREMENT,
buyer_id INT NOT NULL,
paid INT UNSIGNED NOT NULL,
product_id INT NOT NULL,
------------------------------------------------------
TABLE gift
id INT NOT NULL,
giver_id INT NOT NULL,
receiver_id INT NOT NULL,
order_id INT NOT NULL,
我不喜欢这个解决方案,因为查找某个人拥有的所有物品是一项非常复杂的操作(查找收件人为 A 的每个礼物记录 X,并且同一订单不存在以后的礼物记录,结合 find每个订单记录 Y,其中买家是 A,并且该订单不存在礼品记录)但如果这是正确的解决方案,那么我会做的。
【问题讨论】:
-
有上百万种方法可以解决这个问题,但首先想到的两种方法是:1) 创建一个跟踪事务的表。该结构可能类似于:ItemId、CurrentOwnerId、Ordinal(这是允许您维护事件顺序的列)、TransactionType。想到的另一个想法是事件溯源的概念。设置可能有点多,但审计潜力令人难以置信
-
可以合并订单表和礼品表吗?这减少了一些冗余。订单是将物品从 null 转移到用户,成本不为零,而礼物只是从用户到用户的转移,成本为零。
-
如果转移表可以工作,转移表和所有权表之间还有一些冗余,但为了效率,我认为这是可以接受的。您必须在每个只需要确定项目的当前所有者的查询中添加额外的子句,这可能会耗费时间。
-
FWIW 我认为这个问题还可以。我们确实在这里遇到了很多过于宽泛的问题,因此有时会遇到一些边缘案例。我会投票重新开放(我们会看看其他社区成员的想法,我不能保证它会真正开放)。
-
@halfer :谢谢,这是一个有趣的解决方案,但如果提供者和接收者都非空且成本非零,则它允许无效数据。我们的系统只允许玩家赠送物品,不允许出售