我最近在信息学课上学到了规范化,目前我正在开发一个使用SQLite作为后端数据库的多人游戏。
有关它的一些信息:
简化结构看起来有点像:
player_id | level | exp | money | inventory
---------------------------------------------------------
1 | 3 | 120 | 400 | {item a; item b; item c}
好。如您所见,我将以字符串形式将表/数组存储在“inventory”列中。这违反了正常化。
但问题是:为玩家的库存制作一个额外的桌子对我来说只是一个缺点!
当玩家加入时,我从数据库加载他的数据并将其存储在内存中。保存播放器时,我每隔五分钟就会写一次DB。所以我的脚本中实际上只有很少的SQL查询。
如果我在加载时使用额外的表格,我将不得不:
保存时:
如果我将所有玩家数据保存在一个表格中:
我现在该怎么办?
我的论点和情况是否有理由反对规范化?
答案 0 :(得分:12)
您是说您认为从“库存”中解析字符串不需要花费任何时间或精力吗?因为您需要执行从子表中存储/检索库存项目所需的一切,所以您需要对此字符串执行操作,并且使用该字符串您没有任何数据库工具来帮助您执行此操作。
此外,如果您有一个单独的库存项子表,您可以实时添加和删除项目,这意味着如果应用程序崩溃或用户断开连接,它们不会丢失任何内容。
答案 1 :(得分:4)
当你的库存中有十万件商品并且你只想带回两件商品时会发生什么?
如果这是你为一个一个班级一起投掷的东西,并且你不会再使用,那么是的,快速和肮脏的路线对你来说可能是一个更快的选择。
然而,如果这是你将要工作几个月的事情,那么你将会遇到这个设计决定的长期问题。
答案 2 :(得分:4)
不,你的论点无效。它们基本归结为“我希望在我的客户端代码中而不是在SQL中执行所有这些处理,然后将其全部写入单个字段”,因为您仍在执行所有完全相同的处理生成字符串。通过执行此操作,您将删除轻松加载列表的一小部分并丢失与实际item
表的关系的能力,该表可能包含有关项的更多信息(我假设您根据名称对其进行了全部编码)而不是使用内部项ID,这是一个非常糟糕的主意,imo)。
不要这样做。从长远来看,随着您的需求的发展,您想要采取的方法将为您带来更多的工作。
答案 3 :(得分:4)
有很多可能的答案,但适合你的答案就是选择。请注意,您的选择可能需要随时更改。
如果您需要保留的数据量很小(即:适合单个表行)并且您只需要不经常更新该数据,并且您没有任何理由关心该数据的子集,那么你的方法是有道理的。随着时间的推移,你的玩家获得更多的物品并且你为游戏增加了更多的个性化,你可能会开始克服SQLite的限制,你需要改进你的设计。如果您发现需要查询项目列表以确定哪些玩家拥有哪些项目,则需要改进您的设计。
通常认为尽早掌握您的数据架构是一个好主意,但今天参加会议试图猜测您将如何在5到10年内使用您的软件毫无意义。最好能够获得满足今年需求的设计,然后计划在一年后重新评估设计。
答案 4 :(得分:3)
另一种过早优化的情况。
您正在尝试优化您没有任何性能指标的内容。什么是目标平台?如今,即使是最疯狂的计算机也可以每秒运行至少数百次读取操作。然后你为更多的用户添加更好的硬件,然后你可以去云,当你进入谷歌,Twitter和Facebook正在处理的问题空间时,你可以考虑非规范化。即便如此,最好的解决方案是某种键值数据库。
也许您应该查看Database Normalization上的维基百科文章,以提醒您为什么规范化数据库是一件好事。
答案 5 :(得分:2)
您还应该考虑这些项目。这些项目是否对每个用户都是唯一的,或者user1可以使item1和user2具有item1。如果您现在想要更改item1,则必须浏览整个表格并检查哪个用户有此项目。如果你将桌子标准化,这将更容易。
但最后,我认为答案是:这取决于
答案 6 :(得分:1)
我的论点和情况是否合理 反对正常化?
不是基于我到目前为止看到的内容。
通用引擎中的规范化数据库设计(适当地索引并且通过UPSERTS,事务等有效地使用数据库)通常将优于代码,除非代码非常紧密地优化。通常在这样的代码中,通用RDBMS引擎的某些功能被放弃,例如ACID属性或引用完整性之一。
如果你想拥有非常简单的数据访问权限(你想要一个表,一个查询作为一个好处),也许你应该看一个像mongodb或couchdb这样的以文档为中心的数据库。
答案 7 :(得分:0)
您使用任何技术的原因是利用该技术的优势。 SQL有许多你似乎不想使用的优点,如果你不需要它们就没问题。在Neal Stephenson的 Zodiac 中,主角提到从硬件商店购买的东西很少用于其预期目的。软件也是这样的。重要的是它的工作原理,几乎100%的时间都可以工作,并且工作得足够快。
然而,我不禁想到有一天你会有一些过于强大的项目被释放出来,而你将要在数据库层处理这个问题。假设您意外地发布了一些superinstakillmegadeathsword库存物品,这些物品会在使用中杀死50米内的所有物品(包括持有者),并且您想从游戏中删除这些物品。作为对失去superinstakillmegadeathsword项目的人们的道歉,你想为你带走的每个superinstakillmegadeathsword给他们100钱。
使用正确规范化的数据库结构,这是一项微不足道的任务。使用非规范化结构,它会变得更加困难和缓慢。标准化数据库在未来的设计中也将更容易扩展。
所以你确定你不想规范你的数据库吗?