MySql表设计:多个表与多个列

时间:2009-10-29 03:40:31

标签: sql mysql

我很难理解处理相对大量表字段的理想方法,以及它们是否应该拆分成单独的关系表。

我有一组用于基于网络的游戏的表格,包含玩家数据,项目数据,班级数据等。对于这些(玩家/项目/班级)中的每一个,我还需要记录一个统计数量(即健康,精神,盔甲等)。目前,该列表是25个统计数据,这意味着除了已有的列之外,每个表还有50个附加列(类型/值对)。

这开始感到麻烦。

另一种方法是将所有统计数据移动到单独的表中。例如,项目统计信息位于“项目统计信息关系”表中,ID链接到项目和统计信息表。

如果我需要更改统计数量,这将简化表格结构并提供灵活性。但是,它也增加了维护数据的复杂性。如果我添加一个新项目,而不是仅在项目表中插入一行,我现在必须在“项目统计关系”表中插入更多行,以包含它所需的所有统计数据。

保持表格简单是否值得付出额外的努力?


编辑:忘记添加我正在考虑的其他替代方法:将所有统计信息序列化为VARCHAR或TEXT列。这也可以让我灵活地添加任意数量的统计信息(特别是如果我使用TEXT),并且不会给处理它的代码增加任何复杂性。但是,根据我的阅读,TEXT块对性能不利,我必须经常访问它,每次都读取和写入整个块。

5 个答案:

答案 0 :(得分:1)

  

另一种方法是将所有统计数据移动到单独的表中。例如,项目统计信息位于“项目统计信息关系”表中,ID链接到项目和统计信息表。

这是处理业务规则的正确方法。

  

如果我添加一个新项目,而不是仅在项目表中插入一行,我现在必须在“项目统计关系”表中插入更多行,以包含它所需的所有统计数据。

仅当该项目实际使用统计数据时。它允许项目/ etc具有关联的0+统计数据,这意味着您不必为每个新的统计数据更新数据模型以添加列。

风险不佳时,没有性能优势。你会做什么,将被你必须执行的黑客吃掉才能让事情发挥作用。

  

...在多个项目上使用MySQL功能(即添加玩家拥有的所有项目的“强度”),如果其中一些项目甚至没有该统计数据的记录......

使用:

   SELECT IFNULL(SUM(t.value), 0)
     FROM PLAYERS p
     JOIN ITEM_STAT_RELATION itr ON itr.player_id = t.player_id
LEFT JOIN STATS s ON s.stat_id = itr.stat_id
    WHERE p.player_id = ?
      AND ...

LEFT JOIN用于表示支持记录可能不存在,而IFNULL用于处理这种情况,因为它的值为空。 SUM可以处理NULL - 它将值解释为零。

  

...将所有统计信息序列化为VARCHAR或TEXT列。

不要这样做
如果要报告特定统计数据或统计数据组,则连接统计信息列表将很难提取详细信息。由于字符限制,它存在无法将每个统计数据存储在单个列中的风险。

答案 1 :(得分:1)

不确定我理解这条评论:“目前这个列表是25个统计数据,这意味着每个表格都有50个额外的列(类型/值对)”我希望每个统计数据都有一列。或者只有2列(键/值)和许多额外的行

我认为播放器表例如会有如下列: 球员名称,健康,力量,智力等....

然后每行都是:

  • MyHero,250,12,11等......
  • MyOtherHero,200,10,12等......

添加新统计数据只是添加列的一种情况。对于现有玩家,您可能需要对现有行进行数据修复以获得默认值,或者根据其他统计数据修复某些值。

对于玩家可能拥有的物品,您将拥有一个物品表,其中包含每个物品作为单独的行,例如:

  • Itemid,itemname,health,armor等......
  • 1,SwordOfDoom,10,200,......
  • 2,ShieldofReflection,8,300,......

然后你会有一个链接表来将每个玩家与他们拥有的物品联系起来,所以如果MyHero同时拥有两个物品且MyOtherHero只有盾牌,我们可能会有一个Wielding表

  • 玩家ItemID
  • MyHero,1
  • MyHero,2
  • MyOtherHero,2

或者我错过了什么?

答案 2 :(得分:0)

在您的情况下,我认为额外的列属于表。否则,您将得到两个具有相同行数和它们之间的1:1映射的表。这并没有真正简化任何事情!

从概念上讲,我认为它也更正确。所有这些列都是直接链接到其行中项目的数据片段,因此它们属于一起。例如,如果所有的剑都有一套共同的价值观,那就不同了。然后你想说“项目Foo是一个剑,所以请查看类属性表以获取剑项目的统计数据”。

答案 3 :(得分:0)

如果统计数量不会改变,并且您确定不需要新的统计数据,那么您可以使用一个表,多列设计,而不是值/对方法。但是,值/对方法很灵活,允许您在不更改现有数据库架构的情况下添加新统计信息,并节省更多空间。

需要考虑的一些问题

  1. 所有人物/物品都有25个属性吗?如果不是,最好使用值/对
  2. 您是否要纳入某些实体不具备的新统计数据?如果是这样,请使用值/对
  3. 如果您不想使用值对方法,可以尝试序列化。但这会使得统计数据无法搜索(例如,更难,更喜欢列出所有强度大于20的实体)

答案 4 :(得分:0)

多个表更好,它是规范化架构