【问题标题】:Too many fields in MySQL?MySQL中的字段太多?
【发布时间】:2012-03-14 06:25:26
【问题描述】:

几年前,我开发了一个游戏统计网站作为学习项目。它今天仍在使用,我想把它清理一下。

数据库是一个需要改进的领域。我有一个游戏统计表,其中包含 GameID、PlayerID、Kills、Deaths、DamageDealt、DamageTaken 等。该表中总共有大约 50 个字段,将来可能会添加更多字段。什么时候字段太多?它目前有 57,341 行,本身为 153.6 MiB。

我还有一些字段将数组存储在同一个表中的 BLOB 中。数组的一个示例是 Player vs Player 对决。该数组存储该玩家在游戏中杀死另一个玩家的次数。这些是文件大小中较大的字段。是否建议将数组存储在 BLOB 中?

数组看起来像:

        [Killed] => Array
            (
                [SomeDude] => 13
                [GameGuy] => 10
                [AnotherPlayer] => 8
                [YetAnother] => 7
                [BestPlayer] => 3
                [APlayer] => 9
                [WorstPlayer] => 2
            )

这些玩家通常不超过 10 人。

【问题讨论】:

    标签: mysql database-design


    【解决方案1】:

    随着时间的推移向数据库表中添加列并没有错。数据库设计一直在变化。要记住的是数据是如何分组的。我一直将数据库表视为类似项目的集合。

    我考虑的事情如下:

    向一行中插入数据时,有多少列将为空?
    这个新列是否适用于我已有的 80% 的数据?
    我会对该表中的几列进行多次更新吗?
    如果是这样,我是否需要跟踪以前的值以防万一?

    通过考虑这样的数据,您可能会发现您需要将表分解为几个单独的较小的表,这些表通过外键链接在一起。

    【讨论】:

      【解决方案2】:

      使用 mysql,您的硬限制大约为 4000 列(字段)和每行 65Kb 的总存储空间。如果您需要存储大字符串,请使用文本字段,它们存储在磁盘上。确实应该为非文本数据保留 Blob(如果必须的话)。

      一般不要担心数据库的大小,但要考虑结构以及它的组织和索引方式。我见过小型数据库像垃圾一样运行。

      如果您仍然需要数字,当您的总 DB 在 GB 范围内或单个表中超过几十万行时,请开始担心更多事情 - 60K 行中的 150M 并不多,而表扫描不会花费您太多的性能。但是,现在是时候确保在频繁使用的查询上创建良好的覆盖索引了。

      【讨论】:

        【解决方案3】:

        我不希望有一个列数不确定的表(还有更多列),而是有一个关联的标签和值表,因此每个用户都有一个 id,您可以使用该 id 作为进入标签和值表。这样,您只存储每个用户所需的数据。我相信这种方法被称为 EAV(根据 Triztian 的评论),这就是医学数据库的保存方式,因为单个患者有很多潜在的领域,即使任何给定的患者只有极少数具有实际数据的领域.

        所以,你有

        user:
        id | username | some_other_required_field
        
        user_data:
        id | user_id | label | value
        

        现在您可以根据每个用户的需要拥有尽可能多或尽可能少的 user_data 行。

        [编辑]

        至于你的数组,我也会用关系表来处理它。比如:

        player_interraction:
        id | player_id | player_id | interraction_type
        

        您将在此处存储进行交互的两个玩家以及交互的类型。

        【讨论】:

        • 它被称为EAV或Entity-Attribute-Value
        • 作为统计数据的汇总表,我认为可以假设没有动态的“更多内容”,并且他想要添加的列数量有限未来。此外,我认为每个玩家都会使用每一列。因此,可能不需要 EAV 的所有灵活性 - 虽然,我同意 EAV 在这种情况下可以轻松工作。
        • EAV 通常也是性能杀手,它使查询变得更加困难。只有在无法提前定义列时才应该使用它。
        • 我认为 EAV 对这个数据库没有好处。我同意数组是他们自己的表,这就是我可能首先要做的。
        • 我不同意这个观点。如果您有一对一的关系,为什么要分成多个表?有一件事是肯定的:将数据分成的表越多,服务器端代码就越复杂。
        【解决方案4】:

        桌子的设计看起来很不错。只要您存储的列不能从同一行中的其他列计算出来。 IE,您没有存储 SelfKills、OtherDeath 和 TotalDeaths(其中 TotalDeaths = SelfKills + OtherDeath)。那没有意义,可能会从你的桌子上删掉。

        我很想了解更多关于如何将这些数组存储在 BLOB 中的信息 - 它们在 BLOB 中的用途是什么?为什么不将它们规范化为表格以便于数据转换和分析? (或者他们只是在这里存储为一个数组,以便于向最终用户显示数据)。

        另外,我很好奇您的 BLOB 与表的其余部分相比占用了多少数据。一般来说,行的大小并不像行数那么重要,大约 60K 也没什么大不了的。只要您不编写需要检查每个列值的查询(理想情况下,您在尝试编写 where 子句时忽略 blob)。

        【讨论】:

        • “这没有意义,可能会从你的桌子上删掉。”不一定是真的。如果您通过TotalDeaths 进行了大量查询,则将计算后的版本存储在表中是有意义的,这样您就不必每次运行对所有 57,000 行运行计算查询。
        • 你说得对。我有两个不同的想法,“存储信息”是一个,然后我上了“查询大行”,甚至没有一起考虑。
        猜你喜欢
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 2014-11-24
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        • 2012-04-16
        • 1970-01-01
        相关资源
        最近更新 更多